aboutsummaryrefslogtreecommitdiffstats
path: root/Zotlabs
diff options
context:
space:
mode:
authorMax Kostikov <max@kostikov.co>2019-11-11 21:30:38 +0100
committerMax Kostikov <max@kostikov.co>2019-11-11 21:30:38 +0100
commit4a6d050e22c7bfd4c2ae0bb2ff79bedefba33f47 (patch)
treeecc8af0a821436c576e01627ee3c76c6c8ba254d /Zotlabs
parent89342ca9fbf329d5e84839c51f26db19bdd4ac8c (diff)
parentb033597ada02ef045bc9fbdb2237f81935b73e47 (diff)
downloadvolse-hubzilla-4a6d050e22c7bfd4c2ae0bb2ff79bedefba33f47.tar.gz
volse-hubzilla-4a6d050e22c7bfd4c2ae0bb2ff79bedefba33f47.tar.bz2
volse-hubzilla-4a6d050e22c7bfd4c2ae0bb2ff79bedefba33f47.zip
Merge branch 'sse_merge_core' into 'dev'
sse notifications See merge request hubzilla/core!1783
Diffstat (limited to 'Zotlabs')
-rw-r--r--Zotlabs/Lib/Enotify.php136
-rw-r--r--Zotlabs/Lib/ThreadItem.php5
-rw-r--r--Zotlabs/Module/Mail.php2
-rw-r--r--Zotlabs/Module/Sse.php108
-rw-r--r--Zotlabs/Module/Sse_bs.php519
5 files changed, 764 insertions, 6 deletions
diff --git a/Zotlabs/Lib/Enotify.php b/Zotlabs/Lib/Enotify.php
index 92a488f67..de2bfba24 100644
--- a/Zotlabs/Lib/Enotify.php
+++ b/Zotlabs/Lib/Enotify.php
@@ -550,6 +550,11 @@ class Enotify {
if ((\App::$language === 'en' || (! \App::$language)) && strpos($msg,', '))
$msg = substr($msg,strpos($msg,', ')+1);
+ $datarray['id'] = $notify_id;
+ $datarray['msg'] = $msg;
+
+ call_hooks('enotify_store_end', $datarray);
+
$r = q("update notify set msg = '%s' where id = %d and uid = %d",
dbesc($msg),
intval($notify_id),
@@ -838,7 +843,7 @@ class Enotify {
'addr' => (($item[$who]['xchan_addr']) ? $item[$who]['xchan_addr'] : $item[$who]['xchan_url']),
'url' => $item[$who]['xchan_url'],
'photo' => $item[$who]['xchan_photo_s'],
- 'when' => relative_date(($edit)? $item['edited'] : $item['created']),
+ 'when' => (($edit) ? datetime_convert('UTC', date_default_timezone_get(), $item['edited']) : datetime_convert('UTC', date_default_timezone_get(), $item['created'])),
'class' => (intval($item['item_unseen']) ? 'notify-unseen' : 'notify-seen'),
'b64mid' => ((in_array($item['verb'], [ACTIVITY_LIKE, ACTIVITY_DISLIKE])) ? 'b64.' . base64url_encode($item['thr_parent']) : 'b64.' . base64url_encode($item['mid'])),
'notify_id' => 'undefined',
@@ -846,7 +851,7 @@ class Enotify {
'message' => strip_tags(bbcode($itemem_text)),
// these are for the superblock addon
'hash' => $item[$who]['xchan_hash'],
- 'uid' => local_channel(),
+ 'uid' => $item['uid'],
'display' => true
);
@@ -858,4 +863,131 @@ class Enotify {
return $x;
}
+ static public function format_notify($tt) {
+
+ $message = trim(strip_tags(bbcode($tt['msg'])));
+
+ if(strpos($message, $tt['xname']) === 0)
+ $message = substr($message, strlen($tt['xname']) + 1);
+
+ $mid = basename($tt['link']);
+ $mid = ((strpos($mid, 'b64.') === 0) ? @base64url_decode(substr($mid, 4)) : $mid);
+
+ if(in_array($tt['verb'], [ACTIVITY_LIKE, ACTIVITY_DISLIKE])) {
+ // we need the thread parent
+ $r = q("select thr_parent from item where mid = '%s' and uid = %d limit 1",
+ dbesc($mid),
+ intval(local_channel())
+ );
+ $b64mid = ((strpos($r[0]['thr_parent'], 'b64.') === 0) ? $r[0]['thr_parent'] : 'b64.' . base64url_encode($r[0]['thr_parent']));
+ }
+ else {
+ $b64mid = ((strpos($mid, 'b64.') === 0) ? $mid : 'b64.' . base64url_encode($mid));
+ }
+
+ $x = [
+ 'notify_link' => z_root() . '/notify/view/' . $tt['id'],
+ 'name' => $tt['xname'],
+ 'url' => $tt['url'],
+ 'photo' => $tt['photo'],
+ 'when' => datetime_convert('UTC', date_default_timezone_get(), $tt['created']),
+ 'hclass' => (($tt['seen']) ? 'notify-seen' : 'notify-unseen'),
+ 'b64mid' => (($tt['otype'] == 'item') ? $b64mid : 'undefined'),
+ 'notify_id' => (($tt['otype'] == 'item') ? $tt['id'] : 'undefined'),
+ 'message' => $message
+ ];
+
+ return $x;
+
+ }
+
+ static public function format_intros($rr) {
+
+ $x = [
+ 'notify_link' => z_root() . '/connections/ifpending',
+ 'name' => $rr['xchan_name'],
+ 'addr' => $rr['xchan_addr'],
+ 'url' => $rr['xchan_url'],
+ 'photo' => $rr['xchan_photo_s'],
+ 'when' => datetime_convert('UTC', date_default_timezone_get(), $rr['abook_created']),
+ 'hclass' => ('notify-unseen'),
+ 'message' => t('added your channel')
+ ];
+
+ return $x;
+
+ }
+
+ static public function format_files($rr) {
+
+ $x = [
+ 'notify_link' => z_root() . '/sharedwithme',
+ 'name' => $rr['author']['xchan_name'],
+ 'addr' => $rr['author']['xchan_addr'],
+ 'url' => $rr['author']['xchan_url'],
+ 'photo' => $rr['author']['xchan_photo_s'],
+ 'when' => datetime_convert('UTC', date_default_timezone_get(), $rr['created']),
+ 'hclass' => ('notify-unseen'),
+ 'message' => t('shared a file with you')
+ ];
+
+ return $x;
+
+ }
+
+ static public function format_mail($rr) {
+
+ $x = [
+ 'notify_link' => z_root() . '/mail/' . $rr['id'],
+ 'name' => $rr['xchan_name'],
+ 'addr' => $rr['xchan_addr'],
+ 'url' => $rr['xchan_url'],
+ 'photo' => $rr['xchan_photo_s'],
+ 'when' => datetime_convert('UTC', date_default_timezone_get(), $rr['created']),
+ 'hclass' => (intval($rr['mail_seen']) ? 'notify-seen' : 'notify-unseen'),
+ 'message' => t('sent you a private message'),
+ ];
+
+ return $x;
+
+ }
+
+ static public function format_all_events($rr) {
+
+ $bd_format = t('g A l F d') ; // 8 AM Friday January 18
+ $strt = datetime_convert('UTC', (($rr['adjust']) ? date_default_timezone_get() : 'UTC'), $rr['dtstart']);
+ $today = ((substr($strt, 0, 10) === datetime_convert('UTC', date_default_timezone_get(), 'now', 'Y-m-d')) ? true : false);
+ $when = day_translate(datetime_convert('UTC', (($rr['adjust']) ? date_default_timezone_get() : 'UTC'), $rr['dtstart'], $bd_format)) . (($today) ? ' ' . t('[today]') : '');
+
+ $x = [
+ 'notify_link' => z_root() . '/cdav/calendar/' . $rr['event_hash'],
+ 'name' => $rr['xchan_name'],
+ 'addr' => $rr['xchan_addr'],
+ 'url' => $rr['xchan_url'],
+ 'photo' => $rr['xchan_photo_s'],
+ 'when' => $when,
+ 'hclass' => ('notify-unseen'),
+ 'message' => t('posted an event')
+ ];
+
+ return $x;
+
+ }
+
+ static public function format_register($rr) {
+
+ $x = [
+ 'notify_link' => z_root() . '/admin/accounts',
+ 'name' => $rr['account_email'],
+ 'addr' => $rr['account_email'],
+ 'url' => '',
+ 'photo' => z_root() . '/' . get_default_profile_photo(48),
+ 'when' => datetime_convert('UTC', date_default_timezone_get(),$rr['account_created']),
+ 'hclass' => ('notify-unseen'),
+ 'message' => t('requires approval')
+ ];
+
+ return $x;
+
+ }
}
diff --git a/Zotlabs/Lib/ThreadItem.php b/Zotlabs/Lib/ThreadItem.php
index 5e4600df2..174af7f0e 100644
--- a/Zotlabs/Lib/ThreadItem.php
+++ b/Zotlabs/Lib/ThreadItem.php
@@ -369,7 +369,7 @@ class ThreadItem {
'folders' => $body['folders'],
'text' => strip_tags($body['html']),
'id' => $this->get_id(),
- 'mid' => $item['mid'],
+ 'mid' => 'b64.' . base64url_encode($item['mid']),
'parent' => $item['parent'],
'author_id' => (($item['author']['xchan_addr']) ? $item['author']['xchan_addr'] : $item['author']['xchan_url']),
'isevent' => $isevent,
@@ -467,10 +467,9 @@ class ThreadItem {
'previewing' => ($conv->is_preview() ? true : false ),
'preview_lbl' => t('This is an unsaved preview'),
'wait' => t('Please wait'),
- 'submid' => str_replace(['+','='], ['',''], base64_encode($item['mid'])),
'thread_level' => $thread_level,
'settings' => $settings,
- 'thr_parent' => (($item['parent_mid'] != $item['thr_parent']) ? $item['thr_parent'] : '')
+ 'thr_parent' => (($item['parent_mid'] != $item['thr_parent']) ? 'b64.' . base64url_encode($item['thr_parent']) : '')
);
$arr = array('item' => $item, 'output' => $tmp_item);
diff --git a/Zotlabs/Module/Mail.php b/Zotlabs/Module/Mail.php
index 7c344966b..636fc4e33 100644
--- a/Zotlabs/Module/Mail.php
+++ b/Zotlabs/Module/Mail.php
@@ -145,7 +145,7 @@ class Mail extends \Zotlabs\Web\Controller {
$o = '';
nav_set_selected('Mail');
-
+
if(! local_channel()) {
notice( t('Permission denied.') . EOL);
return login();
diff --git a/Zotlabs/Module/Sse.php b/Zotlabs/Module/Sse.php
new file mode 100644
index 000000000..97fee5f49
--- /dev/null
+++ b/Zotlabs/Module/Sse.php
@@ -0,0 +1,108 @@
+<?php
+
+namespace Zotlabs\Module;
+
+use App;
+use Zotlabs\Lib\Apps;
+use Zotlabs\Web\Controller;
+use Zotlabs\Lib\Enotify;
+
+class Sse extends Controller {
+
+ public static $uid;
+ public static $ob_hash;
+ public static $vnotify;
+
+ function init() {
+
+ // this is important!
+ session_write_close();
+
+ $sys = get_sys_channel();
+
+ self::$uid = local_channel();
+ self::$ob_hash = get_observer_hash();
+ self::$vnotify = get_pconfig(self::$uid, 'system', 'vnotify');
+
+ $sleep_seconds = 3;
+
+ header("Content-Type: text/event-stream");
+ header("Cache-Control: no-cache");
+ header("Connection: keep-alive");
+ header("X-Accel-Buffering: no");
+
+ while(true) {
+
+ /**
+ * Update chat presence indication (if applicable)
+ */
+
+ if(self::$ob_hash) {
+ $r = q("select cp_id, cp_room from chatpresence where cp_xchan = '%s' and cp_client = '%s' and cp_room = 0 limit 1",
+ dbesc(self::$ob_hash),
+ dbesc($_SERVER['REMOTE_ADDR'])
+ );
+ $basic_presence = false;
+ if($r) {
+ $basic_presence = true;
+ q("update chatpresence set cp_last = '%s' where cp_id = %d",
+ dbesc(datetime_convert()),
+ intval($r[0]['cp_id'])
+ );
+ }
+ if(! $basic_presence) {
+ q("insert into chatpresence ( cp_xchan, cp_last, cp_status, cp_client)
+ values( '%s', '%s', '%s', '%s' ) ",
+ dbesc(self::$ob_hash),
+ dbesc(datetime_convert()),
+ dbesc('online'),
+ dbesc($_SERVER['REMOTE_ADDR'])
+ );
+ }
+ }
+
+ /**
+ * Chatpresence continued... if somebody hasn't pinged recently, they've most likely left the page
+ * and shouldn't count as online anymore. We allow an expection for bots.
+ */
+ q("delete from chatpresence where cp_last < %s - INTERVAL %s and cp_client != 'auto' ",
+ db_utcnow(),
+ db_quoteinterval('3 MINUTE')
+ );
+
+ $x = q("SELECT v FROM xconfig WHERE xchan = '%s' AND cat = 'sse' AND k = 'notifications'",
+ dbesc(self::$ob_hash)
+ );
+
+ if($x) {
+ $result = unserialize($x[0]['v']);
+ }
+
+ if($result) {
+ echo "event: notifications\n";
+ echo 'data: ' . json_encode($result);
+ echo "\n\n";
+
+ del_xconfig(self::$ob_hash, 'sse', 'notifications');
+ unset($result);
+ }
+
+ // always send heartbeat to detect disconnected clients
+ echo "event: heartbeat\n";
+ echo 'data: {}';
+ echo "\n\n";
+
+ ob_end_flush();
+ flush();
+
+ if(connection_status() != CONNECTION_NORMAL || connection_aborted()) {
+ break;
+ }
+
+ sleep($sleep_seconds);
+
+ }
+
+ }
+
+}
diff --git a/Zotlabs/Module/Sse_bs.php b/Zotlabs/Module/Sse_bs.php
new file mode 100644
index 000000000..672a6c5ef
--- /dev/null
+++ b/Zotlabs/Module/Sse_bs.php
@@ -0,0 +1,519 @@
+<?php
+
+namespace Zotlabs\Module;
+
+use App;
+use Zotlabs\Lib\Apps;
+use Zotlabs\Web\Controller;
+use Zotlabs\Lib\Enotify;
+
+class Sse_bs extends Controller {
+
+ public static $uid;
+ public static $ob_hash;
+ public static $vnotify;
+ public static $evdays;
+ public static $limit;
+ public static $offset;
+ public static $xchans;
+
+ function init() {
+
+ self::$uid = local_channel();
+ self::$ob_hash = get_observer_hash();
+ self::$vnotify = get_pconfig(self::$uid, 'system', 'vnotify');
+ self::$evdays = intval(get_pconfig(self::$uid, 'system', 'evdays'));
+ self::$limit = 100;
+ self::$offset = 0;
+ self::$xchans = '';
+
+ if(!empty($_GET['nquery']) && $_GET['nquery'] !== '%') {
+ $nquery = $_GET['nquery'];
+
+ $x = q("SELECT xchan_hash FROM xchan WHERE xchan_name LIKE '%s' OR xchan_addr LIKE '%s'",
+ dbesc($nquery . '%'),
+ dbesc($nquery . '%')
+ );
+
+ self::$xchans = ids_to_querystr($x, 'xchan_hash', true);
+ }
+
+ if(intval(argv(2)) > 0)
+ self::$offset = argv(2);
+ else
+ $_SESSION['sse_loadtime'] = datetime_convert();
+
+ $network = false;
+ $home = false;
+ $pubs = false;
+ $f = '';
+
+ switch (argv(1)) {
+ case 'network':
+ $network = true;
+ $f = 'bs_network';
+ break;
+ case 'home':
+ $home = true;
+ $f = 'bs_home';
+ break;
+ case 'pubs':
+ $pubs = true;
+ $f = 'bs_pubs';
+ break;
+ default:
+ }
+
+ //hz_syslog('init: ' . argv(1));
+ //hz_syslog('offset: ' . argv(2));
+
+ if(self::$offset && $f) {
+ $result = self::$f(true);
+ json_return_and_die($result);
+ }
+
+ $result = array_merge(
+ self::bs_network($network),
+ self::bs_home($home),
+ self::bs_notify(),
+ self::bs_intros(),
+ self::bs_forums(),
+ self::bs_pubs($pubs),
+ self::bs_files(),
+ self::bs_mail(),
+ self::bs_all_events(),
+ self::bs_register()
+ );
+
+ json_return_and_die($result);
+ }
+
+ function bs_network($notifications) {
+
+ $result['network']['notifications'] = [];
+ $result['network']['count'] = 0;
+
+ if(! self::$uid)
+ return $result;
+
+ $limit = intval(self::$limit);
+ $offset = self::$offset;
+
+ $sql_extra = '';
+ if(! (self::$vnotify & VNOTIFY_LIKE))
+ $sql_extra = " AND verb NOT IN ('" . dbesc(ACTIVITY_LIKE) . "', '" . dbesc(ACTIVITY_DISLIKE) . "') ";
+
+ $sql_extra2 = '';
+ if(self::$xchans)
+ $sql_extra2 = " AND (author_xchan IN (" . self::$xchans . ") OR owner_xchan IN (" . self::$xchans . ")) ";
+
+ $item_normal = item_normal();
+
+ if ($notifications) {
+ $items = q("SELECT * FROM item
+ WHERE uid = %d
+ AND created <= '%s'
+ AND item_unseen = 1 AND item_wall = 0
+ AND author_xchan != '%s'
+ $item_normal
+ $sql_extra
+ $sql_extra2
+ ORDER BY created DESC LIMIT $limit OFFSET $offset",
+ intval(self::$uid),
+ dbescdate($_SESSION['sse_loadtime']),
+ dbesc(self::$ob_hash)
+ );
+
+ if($items) {
+ $result['network']['offset'] = ((count($items) == $limit) ? intval($offset + $limit) : -1);
+ xchan_query($items);
+ foreach($items as $item) {
+ $result['network']['notifications'][] = Enotify::format($item);
+ }
+ }
+ else {
+ $result['network']['offset'] = -1;
+ }
+
+ }
+
+ $r = q("SELECT count(id) as total FROM item
+ WHERE uid = %d and item_unseen = 1 AND item_wall = 0
+ $item_normal
+ $sql_extra
+ AND author_xchan != '%s'",
+ intval(self::$uid),
+ dbesc(self::$ob_hash)
+ );
+
+ if($r)
+ $result['network']['count'] = intval($r[0]['total']);
+
+ return $result;
+ }
+
+ function bs_home($notifications) {
+
+ $result['home']['notifications'] = [];
+ $result['home']['count'] = 0;
+
+ if(! self::$uid)
+ return $result;
+
+ $limit = intval(self::$limit);
+ $offset = self::$offset;
+
+ $sql_extra = '';
+ if(! (self::$vnotify & VNOTIFY_LIKE))
+ $sql_extra = " AND verb NOT IN ('" . dbesc(ACTIVITY_LIKE) . "', '" . dbesc(ACTIVITY_DISLIKE) . "') ";
+
+ $sql_extra2 = '';
+ if(self::$xchans)
+ $sql_extra2 = " AND (author_xchan IN (" . self::$xchans . ") OR owner_xchan IN (" . self::$xchans . ")) ";
+
+
+ $item_normal = item_normal();
+
+ if ($notifications) {
+ $items = q("SELECT * FROM item
+ WHERE uid = %d
+ AND created <= '%s'
+ AND item_unseen = 1 AND item_wall = 1
+ AND author_xchan != '%s'
+ $item_normal
+ $sql_extra
+ $sql_extra2
+ ORDER BY created DESC LIMIT $limit OFFSET $offset",
+ intval(self::$uid),
+ dbescdate($_SESSION['sse_loadtime']),
+ dbesc(self::$ob_hash)
+ );
+
+ if($items) {
+ $result['home']['offset'] = ((count($items) == $limit) ? intval($offset + $limit) : -1);
+ xchan_query($items);
+ foreach($items as $item) {
+ $result['home']['notifications'][] = Enotify::format($item);
+ }
+ }
+ else {
+ $result['home']['offset'] = -1;
+ }
+
+ }
+
+ $r = q("SELECT count(id) as total FROM item
+ WHERE uid = %d and item_unseen = 1 AND item_wall = 1
+ $item_normal
+ $sql_extra
+ AND author_xchan != '%s'",
+ intval(self::$uid),
+ dbesc(self::$ob_hash)
+ );
+
+ if($r)
+ $result['home']['count'] = intval($r[0]['total']);
+
+ return $result;
+ }
+
+ function bs_pubs($notifications) {
+
+ $result['pubs']['notifications'] = [];
+ $result['pubs']['count'] = 0;
+
+ if(! isset($_SESSION['static_loadtime']))
+ $_SESSION['static_loadtime'] = datetime_convert();
+
+ $limit = intval(self::$limit);
+ $offset = self::$offset;
+
+ $sys = get_sys_channel();
+ $sql_extra = '';
+ if(! (self::$vnotify & VNOTIFY_LIKE))
+ $sql_extra = " AND verb NOT IN ('" . dbesc(ACTIVITY_LIKE) . "', '" . dbesc(ACTIVITY_DISLIKE) . "') ";
+
+ $sql_extra2 = '';
+ if(self::$xchans)
+ $sql_extra2 = " AND (author_xchan IN (" . self::$xchans . ") OR owner_xchan IN (" . self::$xchans . ")) ";
+
+ $item_normal = item_normal();
+
+ if ($notifications) {
+ $items = q("SELECT * FROM item
+ WHERE uid = %d
+ AND created <= '%s'
+ AND item_unseen = 1
+ AND author_xchan != '%s'
+ AND created > '%s'
+ $item_normal
+ $sql_extra
+ $sql_extra2
+ ORDER BY created DESC LIMIT $limit OFFSET $offset",
+ intval($sys['channel_id']),
+ dbescdate($_SESSION['sse_loadtime']),
+ dbesc(self::$ob_hash),
+ dbescdate($_SESSION['static_loadtime'])
+ );
+
+ if($items) {
+ $result['pubs']['offset'] = ((count($items) == $limit) ? intval($offset + $limit) : -1);
+ xchan_query($items);
+ foreach($items as $item) {
+ $result['pubs']['notifications'][] = Enotify::format($item);
+ }
+ }
+ else {
+ $result['pubs']['offset'] = -1;
+ }
+
+
+ }
+
+ $r = q("SELECT count(id) as total FROM item
+ WHERE uid = %d AND item_unseen = 1
+ AND created > '%s'
+ $item_normal
+ $sql_extra
+ AND author_xchan != '%s'",
+ intval($sys['channel_id']),
+ dbescdate($_SESSION['static_loadtime']),
+ dbesc(self::$ob_hash)
+ );
+
+ if($r)
+ $result['pubs']['count'] = intval($r[0]['total']);
+
+ return $result;
+ }
+
+
+ function bs_notify() {
+
+ $result['notify']['notifications'] = [];
+ $result['notify']['count'] = 0;
+ $result['notify']['offset'] = -1;
+
+ if(! self::$uid)
+ return $result;
+
+ $r = q("SELECT * FROM notify WHERE uid = %d AND seen = 0 ORDER BY created DESC",
+ intval(self::$uid)
+ );
+ if($r) {
+ foreach($r as $rr) {
+ $result['notify']['notifications'][] = Enotify::format_notify($rr);
+ }
+ $result['notify']['count'] = count($r);
+ }
+
+ return $result;
+
+ }
+
+ function bs_intros() {
+
+ $result['intros']['notifications'] = [];
+ $result['intros']['count'] = 0;
+ $result['intros']['offset'] = -1;
+
+ if(! self::$uid)
+ return $result;
+
+ $r = q("SELECT * FROM abook left join xchan on abook.abook_xchan = xchan.xchan_hash where abook_channel = %d and abook_pending = 1 and abook_self = 0 and abook_ignored = 0 and xchan_deleted = 0 and xchan_orphan = 0 ORDER BY abook_created DESC LIMIT 50",
+ intval(self::$uid)
+ );
+
+ if($r) {
+ foreach($r as $rr) {
+ $result['intros']['notifications'][] = Enotify::format_intros($rr);
+ }
+ $result['intros']['count'] = count($r);
+ }
+
+ return $result;
+
+ }
+
+ function bs_forums() {
+
+ $result['forums']['notifications'] = [];
+ $result['forums']['count'] = 0;
+ $result['forums']['offset'] = -1;
+
+ if(! self::$uid)
+ return $result;
+
+ $forums = get_forum_channels(self::$uid);
+
+ if($forums) {
+ $item_normal = item_normal();
+
+ $sql_extra = '';
+ if(! (self::$vnotify & VNOTIFY_LIKE))
+ $sql_extra = " AND verb NOT IN ('" . dbesc(ACTIVITY_LIKE) . "', '" . dbesc(ACTIVITY_DISLIKE) . "') ";
+
+ $fcount = count($forums);
+ $i = 0;
+
+ for($x = 0; $x < $fcount; $x ++) {
+ $p = q("SELECT oid AS parent FROM term WHERE uid = %d AND ttype = %d AND term = '%s'",
+ intval(self::$uid),
+ intval(TERM_FORUM),
+ dbesc($forums[$x]['xchan_name'])
+ );
+
+ $p_str = ids_to_querystr($p, 'parent');
+ $p_sql = (($p_str) ? "OR parent IN ( $p_str )" : '');
+
+ $r = q("select count(id) as unseen from item
+ where uid = %d and ( owner_xchan = '%s' OR author_xchan = '%s' $p_sql ) and item_unseen = 1 $sql_extra $item_normal",
+ intval(self::$uid),
+ dbesc($forums[$x]['xchan_hash']),
+ dbesc($forums[$x]['xchan_hash'])
+ );
+
+ if($r[0]['unseen']) {
+ $forums[$x]['notify_link'] = (($forums[$x]['private_forum']) ? $forums[$x]['xchan_url'] : z_root() . '/network/?f=&pf=1&unseen=1&cid=' . $forums[$x]['abook_id']);
+ $forums[$x]['name'] = $forums[$x]['xchan_name'];
+ $forums[$x]['addr'] = $forums[$x]['xchan_addr'];
+ $forums[$x]['url'] = $forums[$x]['xchan_url'];
+ $forums[$x]['photo'] = $forums[$x]['xchan_photo_s'];
+ $forums[$x]['unseen'] = $r[0]['unseen'];
+ $forums[$x]['private_forum'] = (($forums[$x]['private_forum']) ? 'lock' : '');
+ $forums[$x]['message'] = (($forums[$x]['private_forum']) ? t('Private forum') : t('Public forum'));
+
+ unset($forums[$x]['abook_id']);
+ unset($forums[$x]['xchan_hash']);
+ unset($forums[$x]['xchan_name']);
+ unset($forums[$x]['xchan_url']);
+ unset($forums[$x]['xchan_photo_s']);
+
+ $i = $i + $r[0]['unseen'];
+
+ }
+ else {
+ unset($forums[$x]);
+ }
+ }
+
+ $result['forums']['count'] = $i;
+ $result['forums']['notifications'] = array_values($forums);
+
+ }
+
+ return $result;
+
+ }
+
+ function bs_files() {
+
+ $result['files']['notifications'] = [];
+ $result['files']['count'] = 0;
+ $result['files']['offset'] = -1;
+
+ if(! self::$uid)
+ return $result;
+
+ $r = q("SELECT * FROM item
+ WHERE verb = '%s'
+ AND obj_type = '%s'
+ AND uid = %d
+ AND owner_xchan != '%s'
+ AND item_unseen = 1",
+ dbesc(ACTIVITY_POST),
+ dbesc(ACTIVITY_OBJ_FILE),
+ intval(self::$uid),
+ dbesc(self::$ob_hash)
+ );
+ if($r) {
+ xchan_query($r);
+ foreach($r as $rr) {
+ $result['files']['notifications'][] = Enotify::format_files($rr);
+ }
+ $result['files']['count'] = count($r);
+ }
+
+ return $result;
+
+ }
+
+ function bs_mail() {
+
+ $result['mail']['notifications'] = [];
+ $result['mail']['count'] = 0;
+ $result['mail']['offset'] = -1;
+
+ if(! self::$uid)
+ return $result;
+
+ $r = q("select mail.*, xchan.* from mail left join xchan on xchan_hash = from_xchan
+ where channel_id = %d and mail_seen = 0 and mail_deleted = 0
+ and from_xchan != '%s' order by created desc",
+ intval(self::$uid),
+ dbesc(self::$ob_hash)
+ );
+
+ if($r) {
+ foreach($r as $rr) {
+ $result['mail']['notifications'][] = Enotify::format_mail($rr);
+ }
+ $result['mail']['count'] = count($r);
+ }
+
+ return $result;
+
+ }
+
+ function bs_all_events() {
+
+ $result['all_events']['notifications'] = [];
+ $result['all_events']['count'] = 0;
+ $result['all_events']['offset'] = -1;
+
+ if(! self::$uid)
+ return $result;
+
+ $r = q("SELECT * FROM event left join xchan on event_xchan = xchan_hash
+ WHERE event.uid = %d AND dtstart < '%s' AND dtstart > '%s' and dismissed = 0
+ and etype in ( 'event', 'birthday' )
+ ORDER BY dtstart DESC",
+ intval(self::$uid),
+ dbesc(datetime_convert('UTC', date_default_timezone_get(), 'now + ' . intval(self::$evdays) . ' days')),
+ dbesc(datetime_convert('UTC', date_default_timezone_get(), 'now - 1 days'))
+ );
+
+ if($r) {
+ foreach($r as $rr) {
+ $result['all_events']['notifications'][] = Enotify::format_all_events($rr);
+ }
+ $result['all_events']['count'] = count($r);
+ }
+
+ return $result;
+ }
+
+ function bs_register() {
+
+ $result['register']['notifications'] = [];
+ $result['register']['count'] = 0;
+ $result['register']['offset'] = -1;
+
+ if(! self::$uid && ! is_site_admin())
+ return $result;
+
+ $r = q("SELECT account_email, account_created from account where (account_flags & %d) > 0",
+ intval(ACCOUNT_PENDING)
+ );
+ if($r) {
+ foreach($r as $rr) {
+ $result['register']['notifications'][] = Enotify::format_register($rr);
+ }
+ $result['register']['count'] = count($r);
+ }
+
+ return $result;
+
+ }
+
+}