'%s' $seenstr $item_normal $sql_extra", intval($sys['channel_id']), dbesc($loadtime) ); if ($pubs) { foreach ($pubs as $p) { if ($p['author_xchan'] === get_observer_hash()) { $my_activity++; } else { $result['pubs']++; } } } } if ((argc() > 1) && (argv(1) === 'pubs') && ($notify_pubs)) { $local_result = []; $r = q( "SELECT * FROM item WHERE uid = %d AND author_xchan != '%s' AND created > '%s' $seenstr $item_normal $sql_extra ORDER BY created DESC LIMIT 300", intval($sys['channel_id']), dbesc(get_observer_hash()), dbesc($loadtime) ); if ($r) { xchan_query($r); foreach ($r as $rr) { $rr['llink'] = str_replace('display/', 'pubstream/?f=&mid=', $rr['llink']); $z = Enotify::format($rr); if ($z) { $local_result[] = $z; } } } json_return_and_die(['notify' => $local_result]); } if ((!local_channel()) || ($result['invalid'])) { json_return_and_die($result); } /** * Everything following is only permitted under the context of a locally authenticated site member. */ /** * Handle "mark all xyz notifications read" requests. */ // mark all items read if (x($_REQUEST, 'markRead') && local_channel() && (!$_SESSION['sudo'])) { switch ($_REQUEST['markRead']) { case 'stream': $r = q( "UPDATE item SET item_unseen = 0 WHERE uid = %d AND item_unseen = 1", intval(local_channel()) ); $_SESSION['loadtime_stream'] = datetime_convert(); PConfig::Set(local_channel(), 'system', 'loadtime_stream', $_SESSION['loadtime_stream']); $_SESSION['loadtime_channel'] = datetime_convert(); PConfig::Set(local_channel(), 'system', 'loadtime_channel', $_SESSION['loadtime_channel']); break; case 'home': $r = q( "UPDATE item SET item_unseen = 0 WHERE uid = %d AND item_unseen = 1 AND item_wall = 1", intval(local_channel()) ); $_SESSION['loadtime_channel'] = datetime_convert(); PConfig::Set(local_channel(), 'system', 'loadtime_channel', $_SESSION['loadtime_channel']); break; case 'all_events': $r = q( "UPDATE event SET dismissed = 1 WHERE uid = %d AND dismissed = 0 AND dtstart < '%s' AND dtstart > '%s' ", intval(local_channel()), dbesc(datetime_convert('UTC', date_default_timezone_get(), 'now + ' . intval($evdays) . ' days')), dbesc(datetime_convert('UTC', date_default_timezone_get(), 'now - 1 days')) ); break; case 'notify': $r = q( "update notify set seen = 1 where uid = %d", intval(local_channel()) ); break; case 'pubs': $_SESSION['loadtime_pubstream'] = datetime_convert(); PConfig::Set(local_channel(), 'system', 'loadtime_pubstream', $_SESSION['loadtime_pubstream']); break; default: break; } } if (x($_REQUEST, 'markItemRead') && local_channel() && (!$_SESSION['sudo'])) { $r = q( "UPDATE item SET item_unseen = 0 WHERE uid = %d AND parent = %d", intval(local_channel()), intval($_REQUEST['markItemRead']) ); $id = intval($_REQUEST['markItemRead']); $seen = PConfig::Get(local_channel(), 'system', 'seen_items', []); if (!in_array($id, $seen)) { $seen[] = $id; } PConfig::Set(local_channel(), 'system', 'seen_items', $seen); } /** * URL ping/something will return detail for "something", e.g. a json list with which to populate a notification * dropdown menu. */ if (argc() > 1 && argv(1) === 'notify') { $t = q( "SELECT * FROM notify WHERE uid = %d AND seen = 0 ORDER BY CREATED DESC", intval(local_channel()) ); if ($t) { foreach ($t as $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 = unpack_link_id($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'] : gen_link_id($r[0]['thr_parent'])); } else { $b64mid = ((strpos($mid, 'b64.') === 0) ? $mid : gen_link_id($mid)); } $notifs[] = array( 'notify_link' => z_root() . '/notify/view/' . $tt['id'], 'name' => $tt['xname'], 'url' => $tt['url'], 'photo' => $tt['photo'], 'when' => relative_date($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 ); } } json_return_and_die(['notify' => $notifs]); } if (argc() > 1 && (argv(1) === 'stream')) { $local_result = []; $item_normal_moderate = $item_normal; $loadtime = get_loadtime('stream'); $r = q( "SELECT * FROM item WHERE uid = %d AND author_xchan != '%s' AND edited > '%s' $seenstr $item_normal_moderate $sql_extra ORDER BY created DESC LIMIT 300", intval(local_channel()), dbesc($ob_hash), dbesc($loadtime) ); if ($r) { xchan_query($r); foreach ($r as $item) { $z = Enotify::format($item); if ($z) { $local_result[] = $z; } } } json_return_and_die(['notify' => $local_result]); } if (argc() > 1 && (argv(1) === 'home')) { $local_result = []; $item_normal_moderate = $item_normal; $sql_extra .= " and item_wall = 1 "; $item_normal_moderate = item_normal_moderate(); $loadtime = get_loadtime('channel'); $r = q( "SELECT * FROM item WHERE uid = %d AND author_xchan != '%s' AND edited > '%s' $seenstr $item_normal_moderate $sql_extra ORDER BY created DESC LIMIT 300", intval(local_channel()), dbesc($ob_hash), dbesc($loadtime) ); if ($r) { xchan_query($r); foreach ($r as $item) { $z = Enotify::format($item); if ($z) { $local_result[] = $z; } } } json_return_and_die(['notify' => $local_result]); } if (argc() > 1 && (argv(1) === 'intros')) { $local_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(local_channel()) ); if ($r) { foreach ($r as $rr) { $local_result[] = [ 'notify_link' => z_root() . '/connections/' . $rr['abook_id'], 'name' => $rr['xchan_name'], 'addr' => $rr['xchan_addr'], 'url' => $rr['xchan_url'], 'photo' => $rr['xchan_photo_s'], 'when' => relative_date($rr['abook_created']), 'hclass' => ('notify-unseen'), 'message' => t('added your channel') ]; } } json_return_and_die(['notify' => $local_result]); } if ((argc() > 1 && (argv(1) === 'register')) && is_site_admin()) { $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[] = array( 'notify_link' => z_root() . '/admin/accounts', 'name' => $rr['account_email'], 'addr' => $rr['account_email'], 'url' => '', 'photo' => z_root() . '/' . Channel::get_default_profile_photo(48), 'when' => relative_date($rr['account_created']), 'hclass' => ('notify-unseen'), 'message' => t('requires approval') ); } } json_return_and_die(['notify' => $result]); } if (argc() > 1 && (argv(1) === 'all_events')) { $bd_format = t('g A l F d'); // 8 AM Friday January 18 $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 LIMIT 1000", intval(local_channel()), dbesc(datetime_convert('UTC', date_default_timezone_get(), 'now + ' . intval($evdays) . ' days')), dbesc(datetime_convert('UTC', date_default_timezone_get(), 'now - 1 days')) ); if ($r) { foreach ($r as $rr) { $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]') : ''); $result[] = array( 'notify_link' => z_root() . '/events', /// @FIXME this takes you to an edit page and it may not be yours, we really want to just view the single event --> '/events/event/' . $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') ); } } json_return_and_die(['notify' => $result]); } if (argc() > 1 && (argv(1) === 'files')) { $result = []; $r = q( "SELECT item.created, xchan.xchan_name, xchan.xchan_addr, xchan.xchan_url, xchan.xchan_photo_s FROM item LEFT JOIN xchan on author_xchan = xchan_hash WHERE item.verb = '%s' AND item.obj_type = '%s' AND item.uid = %d AND item.owner_xchan != '%s' AND item.item_unseen = 1", dbesc(ACTIVITY_POST), dbesc(ACTIVITY_OBJ_FILE), intval(local_channel()), dbesc($ob_hash) ); if ($r) { foreach ($r as $rr) { $result[] = array( 'notify_link' => z_root() . '/sharedwithme', 'name' => $rr['xchan_name'], 'addr' => $rr['xchan_addr'], 'url' => $rr['xchan_url'], 'photo' => $rr['xchan_photo_s'], 'when' => relative_date($rr['created']), 'hclass' => ('notify-unseen'), 'message' => t('shared a file with you') ); } } json_return_and_die(['notify' => $result]); } if (argc() > 1 && (argv(1) === 'reports') && is_site_admin()) { $local_result = []; $r = q( "SELECT item.created, xchan.xchan_name, xchan.xchan_addr, xchan.xchan_url, xchan.xchan_photo_s FROM item LEFT JOIN xchan on author_xchan = xchan_hash WHERE item.type = '%s' AND item.item_unseen = 1", dbesc(ITEM_TYPE_REPORT) ); if ($r) { foreach ($r as $rv) { $result[] = [ 'notify_link' => z_root() . '/reports', 'name' => $rv['xchan_name'], 'addr' => $rv['xchan_addr'], 'url' => $rv['xchan_url'], 'photo' => $rv['xchan_photo_s'], 'when' => relative_date($rv['created']), 'hclass' => ('notify-unseen'), 'message' => t('reported content') ]; } } json_return_and_die(['notify' => $result]); } /** * Normal ping - just the counts, no detail */ if ($vnotify & VNOTIFY_SYSTEM) { $t = q( "select count(*) as total from notify where uid = %d and seen = 0", intval(local_channel()) ); if ($t) { $result['notify'] = intval($t[0]['total']); } } if ($vnotify & VNOTIFY_FILES) { $files = q( "SELECT count(id) as total 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(local_channel()), dbesc($ob_hash) ); if ($files) { $result['files'] = intval($files[0]['total']); } } if ($vnotify & VNOTIFY_NETWORK) { $loadtime = get_loadtime('stream'); $r = q( "SELECT id, author_xchan FROM item WHERE uid = %d and edited > '%s' $seenstr $item_normal $sql_extra ", intval(local_channel()), dbesc($loadtime) ); if ($r) { $arr = array('items' => $r); Hook::call('network_ping', $arr); foreach ($r as $it) { if ($it['author_xchan'] === $ob_hash) { $my_activity++; } else { $result['stream']++; } } } } if (!($vnotify & VNOTIFY_NETWORK)) { $result['stream'] = 0; } if ($vnotify & VNOTIFY_CHANNEL) { $loadtime = get_loadtime('channel'); $r = q( "SELECT id, author_xchan FROM item WHERE item_wall = 1 and uid = %d and edited > '%s' $seenstr $item_normal $sql_extra ", intval(local_channel()), dbesc($loadtime) ); if ($r) { foreach ($r as $it) { if ($it['author_xchan'] === $ob_hash) { $my_activity++; } else { $result['home']++; } } } } if (!($vnotify & VNOTIFY_CHANNEL)) { $result['home'] = 0; } if ($vnotify & VNOTIFY_INTRO) { $intr = q( "SELECT COUNT(abook.abook_id) AS total 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 ", intval(local_channel()) ); if ($intr) { $result['intros'] = intval($intr[0]['total']); } } $channel = App::get_channel(); if ($vnotify & VNOTIFY_REGISTER) { if (App::$config['system']['register_policy'] == REGISTER_APPROVE && is_site_admin()) { $regs = q( "SELECT count(account_id) as total from account where (account_flags & %d) > 0", intval(ACCOUNT_PENDING) ); if ($regs) { $result['register'] = intval($regs[0]['total']); } } } if ($vnotify & VNOTIFY_REPORTS) { if (is_site_admin()) { $reps = q( "SELECT count(id) as total from item where item_type = %d", intval(ITEM_TYPE_REPORT) ); if ($reps) { $result['reports'] = intval($reps[0]['total']); } } } if ($vnotify & (VNOTIFY_EVENT | VNOTIFY_EVENTTODAY | VNOTIFY_BIRTHDAY)) { $events = q( "SELECT etype, dtstart, adjust FROM event WHERE event.uid = %d AND dtstart < '%s' AND dtstart > '%s' and dismissed = 0 and etype in ( 'event', 'birthday' ) ORDER BY dtstart ASC ", intval(local_channel()), dbesc(datetime_convert('UTC', date_default_timezone_get(), 'now + ' . intval($evdays) . ' days')), dbesc(datetime_convert('UTC', date_default_timezone_get(), 'now - 1 days')) ); if ($events) { $result['all_events'] = count($events); if ($result['all_events']) { $str_now = datetime_convert('UTC', date_default_timezone_get(), 'now', 'Y-m-d'); foreach ($events as $x) { $bd = false; if ($x['etype'] === 'birthday') { $result['birthdays']++; $bd = true; } else { $result['events']++; } if (datetime_convert('UTC', ((intval($x['adjust'])) ? date_default_timezone_get() : 'UTC'), $x['dtstart'], 'Y-m-d') === $str_now) { $result['all_events_today']++; if ($bd) { $result['birthdays_today']++; } else { $result['events_today']++; } } } } } } if (!($vnotify & VNOTIFY_EVENT)) { $result['all_events'] = $result['events'] = 0; } if (!($vnotify & VNOTIFY_EVENTTODAY)) { $result['all_events_today'] = $result['events_today'] = 0; } if (!($vnotify & VNOTIFY_BIRTHDAY)) { $result['birthdays'] = 0; } if ($vnotify & VNOTIFY_FORUMS) { $forums = get_forum_channels(local_channel()); if ($forums) { $perms_sql = item_permissions_sql(local_channel()) . item_normal(); $fcount = count($forums); $forums['total'] = 0; for ($x = 0; $x < $fcount; $x++) { $ttype = TERM_FORUM; $p = q("SELECT oid AS parent FROM term WHERE uid = " . intval(local_channel()) . " AND ttype = $ttype AND term = '" . protect_sprintf(dbesc($forums[$x]['xchan_name'])) . "'"); $p = ids_to_querystr($p, 'parent'); $pquery = (($p) ? "OR parent IN ( $p )" : ''); $r = q( "select sum(item_unseen) as unseen from item where uid = %d and ( owner_xchan = '%s' $pquery ) and item_unseen = 1 $perms_sql ", intval(local_channel()), dbesc($forums[$x]['xchan_hash']) ); if ($r[0]['unseen']) { $forums[$x]['notify_link'] = (($forums[$x]['private_forum']) ? $forums[$x]['xchan_url'] : z_root() . '/stream/?f=&pf=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 group') : t('Public group')); $forums['total'] = $forums['total'] + $r[0]['unseen']; 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']); } else { unset($forums[$x]); } } $result['forums'] = $forums['total']; unset($forums['total']); $result['forums_sub'] = $forums; } } // Mark all of the stream notifications seen if all three of them are caught up. // This also resets the pconfig storage for items_seen if ((!$my_activity) && (!(intval($result['home']) + intval($result['stream']) + intval($result['pubs'])))) { PConfig::Delete(local_channel(), 'system', 'seen_items'); $_SESSION['loadtime_channel'] = datetime_convert(); $_SESSION['loadtime_stream'] = datetime_convert(); $_SESSION['loadtime_pubstream'] = datetime_convert(); PConfig::Set(local_channel(), 'system', 'loadtime_channel', $_SESSION['loadtime_channel']); PConfig::Set(local_channel(), 'system', 'loadtime_stream', $_SESSION['loadtime_stream']); PConfig::Set(local_channel(), 'system', 'loadtime_pubstream', $_SESSION['loadtime_pubstream']); } json_return_and_die($result); } }