From 9ac2dadd973d1f2d465a81cb4addaec2333bc043 Mon Sep 17 00:00:00 2001 From: Sebastian Grewe Date: Fri, 7 Jun 2013 14:42:29 +0200 Subject: [PATCH] Progress on notifications * Added main mail class * notification class extends mail class * Added mail template for IDLE workers * Added notification table to SQL structure This works already but once notified the status is not reset as soon as a worker is active again. Need to think of a system to do that automatically. Addresses #116 --- cronjobs/notifications.php | 42 ++++++++++++++ public/include/autoloader.inc.php | 2 + public/include/classes/mail.class.php | 58 +++++++++++++++++++ public/include/classes/notification.class.php | 45 ++++++++++++++ public/include/classes/worker.class.php | 20 +++++++ public/templates/mail/idle_worker.tpl | 9 +++ sql/mmcfe_ng_structure.sql | 20 ++++++- 7 files changed, 193 insertions(+), 3 deletions(-) create mode 100755 cronjobs/notifications.php create mode 100644 public/include/classes/mail.class.php create mode 100644 public/include/classes/notification.class.php create mode 100644 public/templates/mail/idle_worker.tpl diff --git a/cronjobs/notifications.php b/cronjobs/notifications.php new file mode 100755 index 00000000..7bca08ec --- /dev/null +++ b/cronjobs/notifications.php @@ -0,0 +1,42 @@ +#!/usr/bin/php +getAllIdleWorkers(); +if (empty($aWorkers)) { + verbose("No idle workers found\n"); + exit; +} + +foreach ($aWorkers as $aWorker) { + $aData = $aWorker; + $aData['username'] = $user->getUserName($aWorker['account_id']); + $aData['email'] = $user->getUserEmail($aData['username']); + if (!$notification->isNotified($aData)) { + if (!$notification->addNotification('idle_worker', $aData) && $notification->sendMail('sebastian@grewe.ca', 'idle_worker', $aData)) + verbose("Unable to send notification: " . $notification->getError() . "\n"); + } else { + verbose("Already notified for this worker\n"); + } +} +?> diff --git a/public/include/autoloader.inc.php b/public/include/autoloader.inc.php index ea16564e..a78d4a62 100644 --- a/public/include/autoloader.inc.php +++ b/public/include/autoloader.inc.php @@ -14,3 +14,5 @@ require_once(CLASS_DIR . '/worker.class.php'); require_once(CLASS_DIR . '/statistics.class.php'); require_once(CLASS_DIR . '/transaction.class.php'); require_once(CLASS_DIR . '/setting.class.php'); +require_once(CLASS_DIR . '/mail.class.php'); +require_once(CLASS_DIR . '/notification.class.php'); diff --git a/public/include/classes/mail.class.php b/public/include/classes/mail.class.php new file mode 100644 index 00000000..6c7cc0f1 --- /dev/null +++ b/public/include/classes/mail.class.php @@ -0,0 +1,58 @@ +debug = $debug; + } + public function setMysql($mysqli) { + $this->mysqli = $mysqli; + } + public function setSmarty($smarty) { + $this->smarty = $smarty; + } + public function setConfig($config) { + $this->config = $config; + } + + private function checkStmt($bState) { + $this->debug->append("STA " . __METHOD__, 4); + if ($bState ===! true) { + $this->debug->append("Failed to prepare statement: " . $this->mysqli->error); + $this->setErrorMessage('Internal application Error'); + return false; + } + return true; + } + + public function sendMail($email, $template, $vars) { + $this->smarty->assign('WEBSITENAME', $this->config['website']['name']); + $headers = 'From: Website Administration <' . $this->config['website']['email'] . ">\n"; + $headers .= "MIME-Version: 1.0\n"; + $headers .= "Content-Type: text/html; charset=ISO-8859-1\r\n"; + if (mail($email, + $this->smarty->fetch(BASEPATH . 'templates/mail/subject.tpl'), + $this->smarty->fetch(BASEPATH . 'templates/mail/' . $template . '.tpl'), + $headers)) { + return true; + } else { + $this->setErrorMessage("Unable to send mail"); + return false; + } + return false; + } +} + +// Make our class available automatically +$mail = new Mail (); +$mail->setDebug($debug); +$mail->setMysql($mysqli); +$mail->setSmarty($smarty); +$mail->setConfig($config); + +?> diff --git a/public/include/classes/notification.class.php b/public/include/classes/notification.class.php new file mode 100644 index 00000000..a9eca1af --- /dev/null +++ b/public/include/classes/notification.class.php @@ -0,0 +1,45 @@ +mysqli->prepare("SELECT id FROM $this->table WHERE data = ? LIMIT 1"); + if ($stmt && $stmt->bind_param('s', $data) && $stmt->execute() && $stmt->store_result() && $stmt->num_rows == 1) + return true; + // Catchall + // Does not seem to have a notification set + return false; + } + + /** + * Add a new notification to the table + * @param type string Type of the notification + * @return bool + **/ + public function addNotification($type, $data) { + // Store notification data as json + $data = json_encode($data); + $stmt = $this->mysqli->prepare("INSERT INTO $this->table (type, data) VALUES (?,?)"); + if ($stmt && $stmt->bind_param('ss', $type, $data) && $stmt->execute()) + return true; + $this->debug->append("Failed to add notification for $type with $data: " . $this->mysqli->error); + $this->setErrorMessage("Unable to add new notification"); + return false; + } +} + +$notification = new Notification(); +$notification->setDebug($debug); +$notification->setMysql($mysqli); +$notification->setSmarty($smarty); +$notification->setConfig($config); diff --git a/public/include/classes/worker.class.php b/public/include/classes/worker.class.php index 6052eaac..a5052ba9 100644 --- a/public/include/classes/worker.class.php +++ b/public/include/classes/worker.class.php @@ -58,6 +58,26 @@ class Worker { return false; } + /** + * Fetch all IDLE workers that have monitoring enabled + * @param none + * @return data array Workers in IDLE state and monitoring enabled + **/ + public function getAllIdleWorkers() { + $this->debug->append("STA " . __METHOD__, 4); + $stmt = $this->mysqli->prepare(" + SELECT account_id, id, username + FROM " . $this->table . " + WHERE monitor = 1 AND ( SELECT SIGN(COUNT(id)) FROM " . $this->share->getTableName() . " WHERE username = $this->table.username AND time > DATE_SUB(now(), INTERVAL 10 MINUTE)) = 0"); + + if ($this->checkStmt($stmt) && $stmt->execute() && $result = $stmt->get_result()) + return $result->fetch_all(MYSQLI_ASSOC); + // Catchall + $this->setErrorMessage("Unable to fetch IDLE, monitored workers"); + echo $this->mysqli->error; + return false; + } + /** * Fetch all workers for an account * @param account_id int User ID diff --git a/public/templates/mail/idle_worker.tpl b/public/templates/mail/idle_worker.tpl new file mode 100644 index 00000000..a21aaac3 --- /dev/null +++ b/public/templates/mail/idle_worker.tpl @@ -0,0 +1,9 @@ + + +

One of your workers is currently IDLE.

+

Since monitoring is enabled for this worker, this notification was sent.

+

Please check your workers!

+
+
+ + diff --git a/sql/mmcfe_ng_structure.sql b/sql/mmcfe_ng_structure.sql index c3c626bd..a971d455 100644 --- a/sql/mmcfe_ng_structure.sql +++ b/sql/mmcfe_ng_structure.sql @@ -3,7 +3,7 @@ -- http://www.phpmyadmin.net -- -- Host: localhost --- Generation Time: Jun 06, 2013 at 09:01 PM +-- Generation Time: Jun 07, 2013 at 02:42 PM -- Server version: 5.5.31-0ubuntu0.13.04.1 -- PHP Version: 5.4.9-4ubuntu2 @@ -69,6 +69,20 @@ CREATE TABLE IF NOT EXISTS `blocks` ( -- -------------------------------------------------------- +-- +-- Table structure for table `notifications` +-- + +CREATE TABLE IF NOT EXISTS `notifications` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `type` varchar(25) NOT NULL, + `data` text NOT NULL, + `time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + -- -- Table structure for table `pool_worker` -- @@ -136,7 +150,7 @@ CREATE TABLE IF NOT EXISTS `shares_archive` ( PRIMARY KEY (`id`), UNIQUE KEY `share_id` (`share_id`), KEY `time` (`time`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Archive shares for potential later debugging purposes'; +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Archive shares for potential later debugging purposes'; -- -------------------------------------------------------- @@ -153,7 +167,7 @@ CREATE TABLE IF NOT EXISTS `statistics_shares` ( PRIMARY KEY (`id`), KEY `account_id` (`account_id`), KEY `block_id` (`block_id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; +) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- --------------------------------------------------------