diff --git a/cronjobs/auto_payout.php b/cronjobs/auto_payout.php index 36c8a873..63b06d08 100755 --- a/cronjobs/auto_payout.php +++ b/cronjobs/auto_payout.php @@ -61,10 +61,19 @@ if (! empty($users)) { // Create transaction record if ($transaction->addTransaction($aUserData['id'], $dBalance, 'Debit_AP', NULL, $aUserData['coin_address'], 0.1)) { - verbose("OK\n"); + // Notify user via mail + $aMailData['email'] = $user->getUserEmail($user->getUserName($aUserData['id'])); + $aMailData['subject'] = 'Auto Payout Completed'; + $aMailData['amount'] = $dBalance; + if (!$notification->sendNotification($aUserData['id'], 'auto_payout', $aMailData)) { + verbose("NOTIFY FAILED\n"); + } else { + verbose("OK\n"); + } } else { verbose("FAILED\n"); } + } else { verbose("SKIPPED\n"); } diff --git a/cronjobs/findblock.php b/cronjobs/findblock.php index 2f978eed..ead4b61c 100755 --- a/cronjobs/findblock.php +++ b/cronjobs/findblock.php @@ -112,6 +112,16 @@ foreach ($aAllBlocks as $iIndex => $aBlock) { . $strStatus . "\n" ); + + // Notify users + $aAccounts = $notification->getNotificationAccountIdByType('new_block'); + foreach ($aAccounts as $account_id) { + $aMailData['height'] = $aBlock['height']; + $aMailData['subject'] = 'New Block'; + $aMailData['email'] = $user->getUserEmail($user->getUserName($account_id)); + $aMailData['shares'] = $iRoundShares; + $notification->sendNotification($account_id, 'new_block', $aMailData); + } } } ?> diff --git a/cronjobs/notifications.php b/cronjobs/notifications.php index aa2bf8a9..a6b8b101 100755 --- a/cronjobs/notifications.php +++ b/cronjobs/notifications.php @@ -32,20 +32,13 @@ if (empty($aWorkers)) { $aData['username'] = $user->getUserName($aWorker['account_id']); $aData['subject'] = 'IDLE Worker : ' . $aWorker['username']; $aData['email'] = $user->getUserEmail($aData['username']); - if ( $notification->isNotified($aData) ) { - verbose("Worker already notified\n"); - continue; - } - if ($notification->addNotification('idle_worker', $aData) && $notification->sendMail($aData['email'], 'idle_worker', $aData)) { - verbose ("Notified " . $aData['email'] . " for IDLE worker " . $aWorker['username'] . "\n"); - } else { - verbose("Unable to send notification: " . $notification->getError() . "\n"); - } + if (!$notification->sendNotification($aWorker['account_id'], 'idle_worker', $aData)) + verbose($notification->getError() . "\n"); } } // We notified, lets check which recovered -$aNotifications = $notification->getAllActive(); +$aNotifications = $notification->getAllActive('idle_worker'); if (!empty($aNotifications)) { foreach ($aNotifications as $aNotification) { $aData = json_decode($aNotification['data'], true); diff --git a/public/include/classes/mail.class.php b/public/include/classes/mail.class.php index 2800500c..e34423c5 100644 --- a/public/include/classes/mail.class.php +++ b/public/include/classes/mail.class.php @@ -16,6 +16,9 @@ class Mail { public function setSmarty($smarty) { $this->smarty = $smarty; } + public function setUser($user) { + $this->user = $user; + } public function setConfig($config) { $this->config = $config; } @@ -35,14 +38,14 @@ class Mail { return true; } - public function sendMail($email, $template, $aData) { + public function sendMail($template, $aData) { $this->smarty->assign('WEBSITENAME', $this->config['website']['name']); $this->smarty->assign('SUBJECT', $aData['subject']); $this->smarty->assign('DATA', $aData); $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, + if (mail($aData['email'], $this->smarty->fetch(BASEPATH . 'templates/mail/subject.tpl'), $this->smarty->fetch(BASEPATH . 'templates/mail/' . $template . '.tpl'), $headers)) { @@ -61,5 +64,4 @@ $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 index 983db437..b38bac2e 100644 --- a/public/include/classes/notification.class.php +++ b/public/include/classes/notification.class.php @@ -6,6 +6,7 @@ if (!defined('SECURITY')) class Notification extends Mail { var $table = 'notifications'; + var $tableSettings = 'notification_settings'; public function setInactive($id) { $field = array( @@ -22,9 +23,10 @@ class Notification extends Mail { * @param field string Field to update * @return bool **/ - private function updateSingle($id, $field) { + private function updateSingle($id, $field, $table='') { + if (empty($table)) $table = $this->table; $this->debug->append("STA " . __METHOD__, 4); - $stmt = $this->mysqli->prepare("UPDATE $this->table SET " . $field['name'] . " = ? WHERE id = ? LIMIT 1"); + $stmt = $this->mysqli->prepare("UPDATE $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"); @@ -35,22 +37,23 @@ class Notification extends Mail { * so we can avoid duplicate entries **/ public function isNotified($aData) { + $this->debug->append("STA " . __METHOD__, 4); $data = json_encode($aData); $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 // Does not seem to have a notification set - $this->setErrorMessage("Unable to run query: " . $this->mysqli->error); 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()) + public function getAllActive($strType) { + $this->debug->append("STA " . __METHOD__, 4); + $stmt =$this->mysqli->prepare("SELECT id, data FROM $this->table WHERE active = 1 AND type = ?"); + if ($stmt && $stmt->bind_param('s', $strType) && $stmt->execute() && $result = $stmt->get_result()) return $result->fetch_all(MYSQLI_ASSOC); // Catchall return false; @@ -61,14 +64,120 @@ class Notification extends Mail { * @param type string Type of the notification * @return bool **/ - public function addNotification($type, $data) { + public function addNotification($account_id, $type, $data) { + $this->debug->append("STA " . __METHOD__, 4); // Store notification data as json $data = json_encode($data); - $stmt = $this->mysqli->prepare("INSERT INTO $this->table (type, data, active) VALUES (?,?,1)"); - if ($stmt && $stmt->bind_param('ss', $type, $data) && $stmt->execute()) + $stmt = $this->mysqli->prepare("INSERT INTO $this->table (account_id, type, data, active) VALUES (?, ?,?,1)"); + if ($stmt && $stmt->bind_param('iss', $account_id, $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"); + $this->setErrorMessage("Unable to add new notification " . $this->mysqli->error); + return false; + } + + /** + * Fetch notifications for a user account + * @param id int Account ID + * @return array Notification data + **/ + public function getNofifications($account_id) { + $this->debug->append("STA " . __METHOD__, 4); + $stmt = $this->mysqli->prepare("SELECT * FROM $this->table WHERE account_id = ? ORDER BY time DESC"); + if ($stmt && $stmt->bind_param('i', $account_id) && $stmt->execute() && $result = $stmt->get_result()) + return $result->fetch_all(MYSQLI_ASSOC); + // Catchall + return false; + } + + /** + * Fetch notification settings for user account + * @param id int Account ID + * @return array Notification settings + **/ + public function getNotificationSettings($account_id) { + $this->debug->append("STA " . __METHOD__, 4); + $stmt = $this->mysqli->prepare("SELECT * FROM $this->tableSettings WHERE account_id = ?"); + if ($stmt && $stmt->bind_param('i', $account_id) && $stmt->execute() && $result = $stmt->get_result()) { + while ($row = $result->fetch_assoc()) { + $aData[$row['type']] = $row['active']; + } + return $aData; + } + // Catchall + return false; + } + + /** + * Get all accounts that wish to receive a specific notification + * @param strType string Notification type + * @return data array User Accounts + **/ + public function getNotificationAccountIdByType($strType) { + $this->debug->append("STA " . __METHOD__, 4); + $stmt = $this->mysqli->prepare("SELECT account_id FROM $this->tableSettings WHERE type = ? AND active = 1"); + if ($stmt && $stmt->bind_param('s', $strType) && $stmt->execute() && $result = $stmt->get_result()) { + return $result->fetch_all(MYSQLI_ASSOC); + } + // Catchall + return false; + } + + /** + * Update accounts notification settings + * @param account_id int Account ID + * @param data array Data array + * @return bool + **/ + public function updateSettings($account_id, $data) { + $this->debug->append("STA " . __METHOD__, 4); + $failed = $ok = 0; + foreach ($data as $type => $active) { + // Does an entry exist already + $stmt = $this->mysqli->prepare("SELECT * FROM $this->tableSettings WHERE account_id = ? AND type = ?"); + if ($stmt && $stmt->bind_param('is', $account_id, $type) && $stmt->execute() && $stmt->store_result() && $stmt->num_rows() > 0) { + // We found a matching row + $stmt = $this->mysqli->prepare("UPDATE $this->tableSettings SET active = ? WHERE type = ? AND account_id = ?"); + if ($stmt && $stmt->bind_param('isi', $active, $type, $account_id) && $stmt->execute() && $stmt->close()) { + $ok++; + } else { + $failed++; + } + } else { + $stmt = $this->mysqli->prepare("INSERT INTO $this->tableSettings (active, type, account_id) VALUES (?,?,?)"); + if ($stmt && $stmt->bind_param('isi', $active, $type, $account_id) && $stmt->execute()) { + $ok++; + } else { + $failed++; + } + } + } + if ($failed > 0) { + $this->setErrorMessage('Failed to update ' . $failed . ' settings'); + return false; + } + return true; + } + + /** + * Send a specific notification setup in notification_settings + * @param type string Notification type + * @return bool + **/ + public function sendNotification($account_id, $strType, $aMailData) { + // Check if we notified for this event already + if ( $this->isNotified($aMailData) ) { + $this->setErrorMessage('A notification for this event has been sent already'); + return false; + } + // Check if this user wants strType notifications + $stmt = $this->mysqli->prepare("SELECT account_id FROM $this->tableSettings WHERE type = ? AND active = 1 AND account_id = ?"); + if ($stmt && $stmt->bind_param('si', $strType, $account_id) && $stmt->execute() && $stmt->bind_result($id) && $stmt->fetch()) { + if ($stmt->close() && $this->sendMail('notifications/' . $strType, $aMailData) && $this->addNotification($account_id, $strType, $aMailData)) + return true; + } else { + $this->setErrorMessage('User disabled ' . $strType . ' notifications'); + } return false; } } @@ -78,3 +187,5 @@ $notification->setDebug($debug); $notification->setMysql($mysqli); $notification->setSmarty($smarty); $notification->setConfig($config); + +?> diff --git a/public/include/pages/account/edit.inc.php b/public/include/pages/account/edit.inc.php index 1e2941bb..446c13f1 100644 --- a/public/include/pages/account/edit.inc.php +++ b/public/include/pages/account/edit.inc.php @@ -36,12 +36,17 @@ if ( ! $user->checkPin($_SESSION['USERDATA']['id'], $_POST['authPin']) && $_POST } } catch (BitcoinClientException $e) { $_SESSION['POPUP'][] = array('CONTENT' => 'Failed to send LTC, please contact site support immidiately', 'TYPE' => 'errormsg'); - $continue = false; +// $continue = false; } } // Set balance to 0, add to paid out, insert to ledger - if ($continue == true && $transaction->addTransaction($_SESSION['USERDATA']['id'], $dBalance, 'Debit_MP', NULL, $sCoinAddress)) + if ($continue == true && $transaction->addTransaction($_SESSION['USERDATA']['id'], $dBalance, 'Debit_MP', NULL, $sCoinAddress)) { $_SESSION['POPUP'][] = array('CONTENT' => 'Transaction completed', 'TYPE' => 'success'); + $aMailData['email'] = $user->getUserEmail($user->getUserName($_SESSION['USERDATA']['id'])); + $aMailData['amount'] = $dBalance; + $aMailData['subject'] = 'Manual Payout Completed'; + $notification->sendNotification($_SESSION['USERDATA']['id'], 'manual_payout', $aMailData); + } } else { $_SESSION['POPUP'][] = array('CONTENT' => 'Unable to connect to litecoind RPC service', 'TYPE' => 'errormsg'); } diff --git a/public/include/pages/account/notifications.inc.php b/public/include/pages/account/notifications.inc.php new file mode 100644 index 00000000..2ab9c0d0 --- /dev/null +++ b/public/include/pages/account/notifications.inc.php @@ -0,0 +1,25 @@ +updateSettings($_SESSION['USERDATA']['id'], $_REQUEST['data'])) { + $_SESSION['POPUP'][] = array('CONTENT' => 'Updated notification settings'); + } else { + $_SESSION['POPUP'][] = array('CONTENT' => 'Failed to update settings', 'TYPE' => 'errormsg'); + } +} + +// Fetch notifications +$aNotifications = $notification->getNofifications($_SESSION['USERDATA']['id']); +if (!$aNotifications) $_SESSION['POPUP'][] = array('CONTENT' => 'Could not find any notifications', 'TYPE' => 'errormsg'); + +// Fetch user notification settings +$aSettings = $notification->getNotificationSettings($_SESSION['USERDATA']['id']); + +$smarty->assign('NOTIFICATIONS', $aNotifications); +$smarty->assign('SETTINGS', $aSettings); +$smarty->assign('CONTENT', 'default.tpl'); +?> diff --git a/public/templates/mail/notifications/auto_payout.tpl b/public/templates/mail/notifications/auto_payout.tpl new file mode 100644 index 00000000..6d045357 --- /dev/null +++ b/public/templates/mail/notifications/auto_payout.tpl @@ -0,0 +1,8 @@ + +
+An automated payout completed.
+Amount: {$DATA.amount}
+An manual payout request completed.
+Amount: {$DATA.amount}
+A new block has been discovered!
+| ID | +Time | +Type | +Active | +
|---|---|---|---|
| {$NOTIFICATIONS[notification].id} | +{$NOTIFICATIONS[notification].time} | ++ {if $NOTIFICATIONS[notification].type == new_block}New Block + {else if $NOTIFICATIONS[notification].type == auto_payout}Auto Payout + {else if $NOTIFICATIONS[notification].type == idle_worker}IDLE Worker + {else if $NOTIFICATIONS[notification].type == manual_payout}Manual Payout + {/if} + | +
+
+ |
+