* * This source file is subject to the GPL-3.0 license that is bundled * with this source code in the file LICENSE. */ namespace daemons; use Monolog\Handler\StreamHandler; use Monolog\Logger; /** * Quota daemon class. */ class Quota extends AbstractDaemon { private $quota_queue; private $last_message_at; private $bdd; /** * Constructor. * * @param array $phone : A phone table entry */ public function __construct() { $name = 'RaspiSMS Daemon Quota'; $logger = new Logger($name); $logger->pushHandler(new StreamHandler(PWD_LOGS . '/daemons.log', Logger::DEBUG)); $pid_dir = PWD_PID; $no_parent = false; //Rattach to parent so parent can stop it $additional_signals = []; $uniq = true; //Quota should be uniq //Construct the daemon parent::__construct($name, $logger, $pid_dir, $no_parent, $additional_signals, $uniq); parent::start(); } public function run() { $this->bdd = \descartes\Model::_connect(DATABASE_HOST, DATABASE_NAME, DATABASE_USER, DATABASE_PASSWORD, 'UTF8'); $find_message = true; while ($find_message) { //Call message $maxsize = 409600; $message = null; $error_code = null; $success = msg_receive($this->quota_queue, QUEUE_TYPE_QUOTA, $msgtype, $maxsize, $message, true, MSG_IPC_NOWAIT, $error_code); //MSG_IPC_NOWAIT == dont wait if no message found if (!$success && MSG_ENOMSG !== $error_code) { $this->logger->critical('Error for quota queue reading, error code : ' . $error_code); $find_message = false; continue; } if (!$message) { $find_message = false; continue; } $this->logger->info('Check alert level for quota : ' . json_encode($message['id'])); $internal_settings = new \controllers\internals\Setting($this->bdd); $settings = $internal_user->gets_for_user($message['id_user']); $quota_alert_level = false; foreach ($settings as $name => $value) { if ('quota_alert_level', $name) { $quota_alert_level = (float) $value; break; } } if (!$quota_alert_level) { $this->logger->info('Alert is disabled for quota : ' . json_encode($message['id'])); continue; } $internal_quota = new \controllers\internals\Quota($this->bdd); $usage_percentage = $internal_quota->get_usage_percentage($message['id_user']); if ($usage_percentage < $quota_alert_level) { continue; } //If already an alert event since quota start_date, then ignore alert $internal_event = new \controllers\internals\Event($this->bdd); $alert_events = $internal_event->get_events_by_type_and_date_for_user($message['id_user'], 'QUOTA_USAGE_CLOSE', new \DateTime($message['start_date'])); if (count($alert_events)) { continue; } //Alert level reached and no previous alert, we create a new alert $this->logger->info('Trigger alert for quota : ' . json_encode($message['id'])); $internal_event->create($message['id_user'], 'QUOTA_USAGE_CLOSE', 'Reached ' . ($usage_percentage * 100) . '% of SMS quota.'); $user = $internal_user->get($message['id_user']); if (!$user) { $this->logger->info('Cannot find user with id : ' . json_encode($message['id_user'])); continue; } $mailer = new \controllers\internals\Mailer(); $success = $mailer->enqueue($user['email'], EMAIL_QUOTA_USAGE_CLOSE, ['percent' => $usage_percentage]); if (!$success) { $this->logger->error('Cannot enqueue alerting email for quota usage.'); continue; } $this->logger->info('Success sending email'); } //Check quotas every 60 seconds usleep(60 * 1000000); } public function on_start() { //Set last message at to construct time $this->quota_queue = msg_get_queue(QUEUE_ID_QUOTA); $this->logger->info('Starting Quota daemon with pid ' . getmypid()); } public function on_stop() { //Delete queue on daemon close $this->logger->info('Closing queue : ' . QUEUE_ID_EMAIL); msg_remove_queue($this->mailer_queue); $this->logger->info('Stopping Mailer daemon with pid ' . getmypid()); } public function handle_other_signals($signal) { $this->logger->info('Signal not handled by ' . $this->name . ' Daemon : ' . $signal); } }