Skip to content

Commit 6640f1f

Browse files
authored
Merge pull request #2540 from blondak/development
#2539 - Feature request: Pushover.net notifications
2 parents a1cb113 + bcfd7cf commit 6640f1f

File tree

22 files changed

+634
-80
lines changed

22 files changed

+634
-80
lines changed

include/autoloader.inc.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,5 +78,8 @@
7878
require_once(CLASS_DIR . '/roundstats.class.php');
7979
require_once(CLASS_DIR . '/news.class.php');
8080
require_once(CLASS_DIR . '/api.class.php');
81+
require_once(CLASS_DIR . '/usersettings.class.php');
82+
require_once(CLASS_DIR . '/ipushnotification.interface.php');
83+
require_once(CLASS_DIR . '/pushnotification.class.php');
8184
require_once(INCLUDE_DIR . '/lib/Michelf/Markdown.php');
8285
require_once(INCLUDE_DIR . '/lib/scrypt.php');

include/classes/base.class.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ class Base {
1616
public function getTableName() {
1717
return $this->table;
1818
}
19+
20+
protected $debug;
1921
public function setDebug($debug) {
2022
$this->debug = $debug;
2123
}
@@ -25,9 +27,13 @@ public function setCoin($coin) {
2527
public function setCoinAddress($coin_address) {
2628
$this->coin_address = $coin_address;
2729
}
30+
31+
public $log;
2832
public function setLog($log) {
2933
$this->log = $log;
3034
}
35+
36+
protected $mysqli;
3137
public function setMysql($mysqli) {
3238
$this->mysqli = $mysqli;
3339
}
@@ -40,6 +46,10 @@ public function setSalt($salt) {
4046
public function setSalty($salt) {
4147
$this->salty = $salt;
4248
}
49+
/**
50+
* @var Smarty
51+
*/
52+
var $smarty;
4353
public function setSmarty($smarty) {
4454
$this->smarty = $smarty;
4555
}
@@ -52,6 +62,8 @@ public function setSessionManager($session) {
5262
public function setConfig($config) {
5363
$this->config = $config;
5464
}
65+
66+
protected $aErrorCodes;
5567
public function setErrorCodes(&$aErrorCodes) {
5668
$this->aErrorCodes =& $aErrorCodes;
5769
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<?php
2+
interface IPushNotification {
3+
public static function getName();
4+
public static function getParameters();
5+
public function notify($message, $severity, $event);
6+
}

include/classes/notification.class.php

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -149,14 +149,27 @@ public function sendNotification($account_id, $strType, $aMailData) {
149149
return false;
150150
}
151151
// Check if this user wants strType notifications
152-
$stmt = $this->mysqli->prepare("SELECT account_id FROM $this->tableSettings WHERE type = ? AND active = 1 AND account_id = ?");
153-
if ($stmt && $stmt->bind_param('si', $strType, $account_id) && $stmt->execute() && $stmt->bind_result($id) && $stmt->fetch()) {
154-
if ($stmt->close() && $this->sendMail('notifications/' . $strType, $aMailData) && $this->addNotification($account_id, $strType, $aMailData)) {
155-
return true;
156-
} else {
157-
$this->setErrorMessage('SendMail call failed: ' . $this->getError());
158-
return false;
159-
}
152+
$stmt = $this->mysqli->prepare("SELECT type FROM $this->tableSettings WHERE type IN (?, ?) AND active = 1 AND account_id = ?");
153+
if ($stmt && $stmt->bind_param('ssi', $strType, substr('push_'.$strType, 0, 15), $account_id) && $stmt->execute() && $result = $stmt->get_result()) {
154+
$types = array_map(function($a){ return reset($a);}, $result->fetch_all(MYSQLI_ASSOC));
155+
$stmt->close();
156+
$result = true;
157+
foreach ($types as $type){
158+
if (strpos($type, 'push_') === 0){
159+
if (PushNotification::Instance() instanceof PushNotification){
160+
$result &= PushNotification::Instance()->sendNotification($account_id, $strType, $aMailData);
161+
}
162+
} else {
163+
$result &= $this->sendMail('notifications/' . $strType, $aMailData);
164+
}
165+
}
166+
if ($result){
167+
$this->addNotification($account_id, $strType, $aMailData);
168+
return true;
169+
} else {
170+
$this->setErrorMessage('SendMail call failed: ' . $this->getError());
171+
return false;
172+
}
160173
} else {
161174
$this->setErrorMessage('User disabled ' . $strType . ' notifications');
162175
return true;
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<?php
2+
class Notifications_NotifyMyAndroid implements IPushNotification {
3+
4+
private $apiKey;
5+
public function __construct($apikey){
6+
$this->apiKey = $apikey;
7+
}
8+
9+
static $priorities = array(
10+
0 => 'info',
11+
2 => 'error',
12+
);
13+
14+
public static function getName(){
15+
return "notifymyandroid.com";
16+
}
17+
18+
public static function getParameters(){
19+
return array(
20+
'apikey' => 'API key',
21+
);
22+
}
23+
24+
public function notify($message, $severity = 'info', $event = null){
25+
curl_setopt_array($ch = curl_init(), array(
26+
CURLOPT_URL => "https://www.notifymyandroid.com/publicapi/notify",
27+
CURLOPT_POST => true,
28+
CURLOPT_RETURNTRANSFER => true,
29+
CURLOPT_POSTFIELDS => http_build_query($data = array(
30+
"apikey" => $this->apiKey,
31+
"application" => "CryptoGlance",
32+
"description" => $message,
33+
"content-type" => "text/html",
34+
"event" => $event,
35+
"priority" => array_search($severity, self::$priorities),
36+
)),
37+
));
38+
curl_exec($ch);
39+
curl_close($ch);
40+
}
41+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<?php
2+
class Notifications_Pushover implements IPushNotification {
3+
4+
private $token;
5+
private $user;
6+
public function __construct($token, $user){
7+
$this->token = $token;
8+
$this->user = $user;
9+
}
10+
11+
static $priorities = array(
12+
0 => 'info',
13+
1 => 'warning',
14+
2 => 'error',
15+
);
16+
17+
public static function getName(){
18+
return "pushover.net";
19+
}
20+
21+
public static function getParameters(){
22+
return array(
23+
'token' => 'API Token/Key',
24+
'user' => 'Your User Key',
25+
);
26+
}
27+
28+
public function notify($message, $severity = 'info', $event = null){
29+
curl_setopt_array($ch = curl_init(), array(
30+
CURLOPT_URL => "https://api.pushover.net/1/messages.json",
31+
CURLOPT_POST => true,
32+
CURLOPT_RETURNTRANSFER => true,
33+
CURLOPT_POSTFIELDS => http_build_query($data = array(
34+
"token" => $this->token,
35+
"user" => $this->user,
36+
"message" => $code = strip_tags(preg_replace('/<([\/]?)span[^>]*>/i', '<\1b>', $message), "<b><i><u><a><font><p><br>"),
37+
"title" => strip_tags($event),
38+
"priority" => (int)array_search($severity, self::$priorities),
39+
"timestamp" => time(),
40+
"html" => preg_match('/<[^>]+>/', $code),
41+
)),
42+
));
43+
curl_exec($ch);
44+
curl_close($ch);
45+
}
46+
}
Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
<?php
2+
$defflip = (!cfip()) ? exit(header('HTTP/1.1 401 Unauthorized')) : 1;
3+
4+
class PushNotification extends Base {
5+
var $tableSettings = 'push_notification_settings';
6+
7+
private static function getClassesInFile($file){
8+
$classes = array();
9+
$tokens = token_get_all(file_get_contents($file));
10+
$count = count($tokens);
11+
for ($i = 2; $i < $count; $i++) {
12+
if ($tokens[$i - 2][0] == T_CLASS && $tokens[$i - 1][0] == T_WHITESPACE && $tokens[$i][0] == T_STRING) {
13+
$class_name = $tokens[$i][1];
14+
$classes[] = $class_name;
15+
}
16+
}
17+
return $classes;
18+
}
19+
20+
private static $classes = null;
21+
public function getClasses(){
22+
if (self::$classes === null){
23+
$directory = new DirectoryIterator(__DIR__.'/push_notification');
24+
foreach ($directory as $fileInfo) {
25+
if (($fileInfo->getExtension() != 'php') || $fileInfo->isDot()) {
26+
continue;
27+
}
28+
foreach (self::getClassesInFile($fileInfo->getRealPath()) as $class){
29+
if (!class_exists($class)){
30+
include $fileInfo->getRealPath();
31+
}
32+
$cr = new ReflectionClass($class);
33+
if ($cr->isSubclassOf('IPushNotification')){
34+
self::$classes[$class] = array($fileInfo->getFilename(), $cr->getMethod('getName')->invoke(null), $cr->getMethod('getParameters')->invoke(null));
35+
}
36+
}
37+
}
38+
}
39+
return self::$classes;
40+
}
41+
42+
public function getClassesForSmarty(){
43+
$c = $this->getClasses();
44+
return array_map(function($a, $b){
45+
return array(
46+
'class' => $b,
47+
'file' => $a[0],
48+
'name' => $a[1],
49+
'parameters' => $a[2],
50+
);
51+
}, $c, array_keys($c));
52+
}
53+
54+
/**
55+
* @param string|array $notificator
56+
* @param array $data
57+
* @return IPushNotification|bool
58+
*/
59+
public function getNotificatorInstance($notificator, $data){
60+
$class = null;
61+
$file = null;
62+
63+
if (is_array($notificator)){
64+
if (count($notificator) == 2){
65+
list($class, $file) = $notificator;
66+
} else {
67+
$class = reset($notificator);
68+
}
69+
} else {
70+
$class = $notificator;
71+
}
72+
73+
if (!class_exists($class)){
74+
if ($file === null){
75+
foreach (self::getClasses() as $_class => $_info){
76+
if ($_class == $class){
77+
$file = $_info[0];
78+
break;
79+
}
80+
}
81+
} else {
82+
include __DIR__.'/push_notification/'.$file;
83+
}
84+
if (!class_exists($class)){
85+
return false;
86+
}
87+
}
88+
$cr = new ReflectionClass($class);
89+
$constructor = $cr->getConstructor();
90+
$constructorParameters = array();
91+
foreach (array_map(function($a){ return $a->getName();}, $constructor->getParameters()) as $param){
92+
$constructorParameters[] = array_key_exists($param, $data)?$data[$param]:null;
93+
}
94+
$instance = $cr->newInstanceArgs($constructorParameters);
95+
return $instance;
96+
}
97+
98+
/**
99+
* Update accounts push notification settings
100+
* @param account_id int Account ID
101+
* @param data array Data array
102+
* @return bool
103+
**/
104+
public function updateSettings($account_id, $data) {
105+
UserSettings::construct($account_id)->PushNotifications = $data;
106+
return true;
107+
}
108+
109+
/**
110+
* Fetch notification settings for user account
111+
* @param id int Account ID
112+
* @return array Notification settings
113+
**/
114+
public function getNotificationSettings($account_id) {
115+
if ($settings = UserSettings::construct($account_id)->PushNotifications){
116+
return $settings;
117+
}
118+
return array(
119+
'class' => false,
120+
'params' => null,
121+
'file' => null,
122+
);
123+
}
124+
125+
private static $instance = null;
126+
/**
127+
* @param PushNotification $instance
128+
*/
129+
public static function Instance($instance = null){
130+
if (func_num_args() == 0){
131+
return self::$instance;
132+
}
133+
return self::$instance = $instance;
134+
}
135+
136+
public function sendNotification($account_id, $template, $aData){
137+
$settings = $this->getNotificationSettings($account_id);
138+
if ($settings['class']){
139+
$instance = $this->getNotificatorInstance(array($settings['class'], $settings['file']), $settings['params']);
140+
if ($instance){
141+
$this->smarty->assign('WEBSITENAME', $this->setting->getValue('website_name'));
142+
$this->smarty->assign('SUBJECT', $aData['subject']);
143+
$this->smarty->assign('DATA', $aData);
144+
145+
$message = false;
146+
foreach (array('/mail/push_notifications/', '/mail/notifications/') as $dir){
147+
$this->smarty->clearCache($templateFile = TEMPLATE_DIR.$dir.$template.'.tpl');
148+
try {
149+
$message = $this->smarty->fetch($templateFile);
150+
break;
151+
} catch (SmartyException $e){
152+
153+
}
154+
}
155+
if ($message){
156+
$instance->notify($message, 'info', $aData['subject']);
157+
}
158+
}
159+
}
160+
return true;
161+
}
162+
}
163+
164+
$pushnotification = PushNotification::Instance(new PushNotification());
165+
$pushnotification->setDebug($debug);
166+
$pushnotification->setLog($log);
167+
$pushnotification->setMysql($mysqli);
168+
$pushnotification->setSmarty($smarty);
169+
$pushnotification->setConfig($config);
170+
$pushnotification->setSetting($setting);
171+
$pushnotification->setErrorCodes($aErrorCodes);

include/classes/transaction.class.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,7 @@ private function createDebitRecord($account_id, $coin_address, $amount, $type) {
430430
$aMailData['email'] = $this->user->getUserEmailById($account_id);
431431
$aMailData['subject'] = $type . ' Completed';
432432
$aMailData['amount'] = $amount;
433+
$aMailData['currency'] = $this->config['currency'];
433434
if (!$this->notification->sendNotification($account_id, 'payout', $aMailData)) {
434435
$this->setErrorMessage('Failed to send notification email to users address: ' . $aMailData['email'] . 'ERROR: ' . $this->notification->getCronError());
435436
}

include/classes/user.class.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ public function checkLogin($username, $password) {
244244
$notifs->setSetting($this->setting);
245245
$notifs->setErrorCodes($this->aErrorCodes);
246246
$ndata = $notifs->getNotificationSettings($uid);
247-
if (@$ndata['success_login'] == 1) {
247+
if ((array_key_exists('push_success_lo', $ndata) && $ndata['push_success_lo']) || (array_key_exists('success_login', $ndata) && $ndata['success_login'])){
248248
// seems to be active, let's send it
249249
$aDataN['username'] = $username;
250250
$aDataN['email'] = $this->getUserEmail($username);

0 commit comments

Comments
 (0)