diff --git a/cronjobs/notifications.php b/cronjobs/notifications.php index 7bca08ec..e70d2b07 100755 --- a/cronjobs/notifications.php +++ b/cronjobs/notifications.php @@ -22,21 +22,31 @@ limitations under the License. // Include all settings and classes require_once('shared.inc.php'); +// Find all IDLE workers $aWorkers = $worker->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"); +} else { + 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"); + } } } +// We notified, lets check which recovered +$aNotifications = $notification->getAllActive(); +foreach ($aNotifications as $aNotification) { + $aData = json_decode($aNotification['data'], true); + $aWorker = $worker->getWorker($aData['id']); + if ($aWorker['active'] == 1) + if (!$notification->setInactive($aNotification['id'])) + verbose("Failed to set notification inactive for " . $aWorker['username'] . "\n"); +} + ?> diff --git a/public/include/classes/mail.class.php b/public/include/classes/mail.class.php index 6c7cc0f1..a1cf2137 100644 --- a/public/include/classes/mail.class.php +++ b/public/include/classes/mail.class.php @@ -20,7 +20,7 @@ class Mail { $this->config = $config; } - private function checkStmt($bState) { + function checkStmt($bState) { $this->debug->append("STA " . __METHOD__, 4); if ($bState ===! true) { $this->debug->append("Failed to prepare statement: " . $this->mysqli->error); diff --git a/public/include/classes/notification.class.php b/public/include/classes/notification.class.php index a9eca1af..9a6dcf3b 100644 --- a/public/include/classes/notification.class.php +++ b/public/include/classes/notification.class.php @@ -7,13 +7,36 @@ if (!defined('SECURITY')) class Notification extends Mail { var $table = 'notifications'; + public function setInactive($id) { + $field = array( + 'name' => 'active', + 'type' => 'i', + 'value' => 0 + ); + return $this->updateSingle($id, $field); + } + + /** + * Update a single row in a table + * @param userID int Account ID + * @param field string Field to update + * @return bool + **/ + private function updateSingle($id, $field) { + $this->debug->append("STA " . __METHOD__, 4); + $stmt = $this->mysqli->prepare("UPDATE $this->table SET " . $field['name'] . " = ? WHERE id = ? LIMIT 1"); + if ($this->checkStmt($stmt) && $stmt->bind_param($field['type'].'i', $field['value'], $id) && $stmt->execute()) + return true; + $this->debug->append("Unable to update " . $field['name'] . " with " . $field['value'] . " for ID $id"); + return false; + } /** * We check our notification table for existing data * so we can avoid duplicate entries **/ public function isNotified($aData) { $data = json_encode($aData); - $stmt = $this->mysqli->prepare("SELECT id FROM $this->table WHERE data = ? LIMIT 1"); + $stmt = $this->mysqli->prepare("SELECT id FROM $this->table WHERE data = ? AND active = 1 LIMIT 1"); if ($stmt && $stmt->bind_param('s', $data) && $stmt->execute() && $stmt->store_result() && $stmt->num_rows == 1) return true; // Catchall @@ -21,6 +44,17 @@ class Notification extends Mail { return false; } + /** + * Get all active notifications + **/ + public function getAllActive() { + $stmt =$this->mysqli->prepare("SELECT id, data FROM $this->table WHERE active = 1 LIMIT 1"); + if ($stmt && $stmt->execute() && $result = $stmt->get_result()) + return $result->fetch_all(MYSQLI_ASSOC); + // Catchall + return false; + } + /** * Add a new notification to the table * @param type string Type of the notification @@ -29,7 +63,7 @@ class Notification extends Mail { 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 (?,?)"); + $stmt = $this->mysqli->prepare("INSERT INTO $this->table (type, data, active) VALUES (?,?,1)"); 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); diff --git a/public/include/classes/worker.class.php b/public/include/classes/worker.class.php index a5052ba9..6a9f6524 100644 --- a/public/include/classes/worker.class.php +++ b/public/include/classes/worker.class.php @@ -78,6 +78,27 @@ class Worker { return false; } + /** + * Fetch a specific worker and its status + * @param id int Worker ID + * @return mixed array Worker details + **/ + public function getWorker($id) { + $this->debug->append("STA " . __METHOD__, 4); + $stmt = $this->mysqli->prepare(" + SELECT id, username, password, monitor, + ( SELECT SIGN(COUNT(id)) FROM " . $this->share->getTableName() . " WHERE username = $this->table.username AND time > DATE_SUB(now(), INTERVAL 10 MINUTE)) AS active, + ( SELECT ROUND(COUNT(id) * POW(2, " . $this->config['difficulty'] . ")/600/1000) FROM " . $this->share->getTableName() . " WHERE username = $this->table.username AND time > DATE_SUB(now(), INTERVAL 10 MINUTE)) AS hashrate + FROM $this->table + WHERE id = ? + "); + if ($this->checkStmt($stmt) && $stmt->bind_param('i', $id) && $stmt->execute() && $result = $stmt->get_result()) + return $result->fetch_assoc(); + // Catchall + echo $this->mysqli->error; + return false; + } + /** * Fetch all workers for an account * @param account_id int User ID