From 820ded2c2d3cbbb170f990a2f0c162decb0029d7 Mon Sep 17 00:00:00 2001 From: Michael Vogel Date: Mon, 10 Aug 2015 21:33:57 +0200 Subject: [PATCH 1/7] Support for the new nodeinfo protocol that will replace statistics.json --- include/poller.php | 4 + mod/_well_known.php | 4 + mod/nodeinfo.php | 218 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 226 insertions(+) create mode 100644 mod/nodeinfo.php diff --git a/include/poller.php b/include/poller.php index 7cc1a2852..b72a4a823 100644 --- a/include/poller.php +++ b/include/poller.php @@ -36,6 +36,7 @@ function poller_run(&$argv, &$argc){ require_once('include/email.php'); require_once('include/socgraph.php'); require_once('include/pidfile.php'); + require_once('mod/nodeinfo.php'); load_config('config'); load_config('system'); @@ -117,6 +118,9 @@ function poller_run(&$argv, &$argc){ // Check every conversation check_conversations(false); + // update nodeinfo data + nodeinfo_cron(); + // To-Do: Regenerate usage statistics // q("ANALYZE TABLE `item`"); diff --git a/mod/_well_known.php b/mod/_well_known.php index 3d722f722..1271e12f4 100644 --- a/mod/_well_known.php +++ b/mod/_well_known.php @@ -1,5 +1,6 @@ argc > 1) { @@ -10,6 +11,9 @@ function _well_known_init(&$a){ case "x-social-relay": wk_social_relay($a); break; + case "nodeinfo": + nodeinfo_wellknown($a); + break; } } http_status_exit(404); diff --git a/mod/nodeinfo.php b/mod/nodeinfo.php new file mode 100644 index 000000000..bf1d4ef3e --- /dev/null +++ b/mod/nodeinfo.php @@ -0,0 +1,218 @@ + array("rel" => "http://nodeinfo.diaspora.software/ns/schema/1.0", + "href" => $a->get_baseurl()."/nodeinfo/1.0")); + + header('Content-type: application/json; charset=utf-8'); + echo json_encode($nodeinfo, true); + exit; +} + +function nodeinfo_init(&$a){ + if (!get_config("system", "nodeinfo")) { + http_status_exit(404); + killme(); + } + + if (($a->argc != 2) OR ($a->argv[1] != "1.0")) { + http_status_exit(404); + killme(); + } + + $smtp = (function_exists("imap_open") AND !get_config("system","imap_disabled") AND !get_config("system","dfrn_only")); + + $nodeinfo = array(); + $nodeinfo["version"] = "1.0"; + $nodeinfo["software"] = array("name" => "friendica", "version" => FRIENDICA_VERSION."-".DB_UPDATE_VERSION); + + $nodeinfo["protocols"] = array(); + $nodeinfo["protocols"]["inbound"] = array(); + $nodeinfo["protocols"]["outbound"] = array(); + + if (get_config("system","diaspora_enabled")) { + $nodeinfo["protocols"]["inbound"][] = "diaspora"; + $nodeinfo["protocols"]["outbound"][] = "diaspora"; + } + + $nodeinfo["protocols"]["inbound"][] = "friendica"; + $nodeinfo["protocols"]["outbound"][] = "friendica"; + + if (!get_config("system","ostatus_disabled")) { + $nodeinfo["protocols"]["inbound"][] = "gnusocial"; + $nodeinfo["protocols"]["outbound"][] = "gnusocial"; + } + + if ($smtp) { + $nodeinfo["protocols"]["inbound"][] = "smtp"; + $nodeinfo["protocols"]["outbound"][] = "smtp"; + } + + $nodeinfo["services"] = array(); + + if (nodeinfo_plugin_enabled("appnet") OR nodeinfo_plugin_enabled("buffer")) + $nodeinfo["services"][] = "appnet"; + + if (nodeinfo_plugin_enabled("blogger")) + $nodeinfo["services"][] = "blogger"; + + if (get_config("system","diaspora_enabled")) + $nodeinfo["services"][] = "diaspora"; + + if (nodeinfo_plugin_enabled("dreamwidth")) + $nodeinfo["services"][] = "dreamwidth"; + + if (nodeinfo_plugin_enabled("fbpost") OR nodeinfo_plugin_enabled("buffer")) + $nodeinfo["services"][] = "facebook"; + + $nodeinfo["services"][] = " friendica"; + + if (nodeinfo_plugin_enabled("statusnet") OR !get_config("system","ostatus_disabled")) + $nodeinfo["services"][] = "gnusocial"; + + if (nodeinfo_plugin_enabled("fpluspost") OR nodeinfo_plugin_enabled("buffer")) + $nodeinfo["services"][] = "google"; + + if (nodeinfo_plugin_enabled("libertree")) + $nodeinfo["services"][] = "libertree"; + + if (nodeinfo_plugin_enabled("buffer")) + $nodeinfo["services"][] = "linkedin"; + + if (nodeinfo_plugin_enabled("ljpost")) + $nodeinfo["services"][] = "livejournal"; + + if (nodeinfo_plugin_enabled("pumpio")) + $nodeinfo["services"][] = "pumpio"; + + if ($smtp) + $nodeinfo["services"][] = "smtp"; + + if (nodeinfo_plugin_enabled("tumblr")) + $nodeinfo["services"][] = "tumblr"; + + if (nodeinfo_plugin_enabled("twitter")) + $nodeinfo["services"][] = "twitter"; + + if (nodeinfo_plugin_enabled("wordpress")) + $nodeinfo["services"][] = "wppost"; + + $nodeinfo["openRegistrations"] = ($a->config['register_policy'] != 0); + + $nodeinfo["usage"] = array(); + $nodeinfo["usage"]["users"] = array("total" => get_config("nodeinfo","total_users"), + "activeHalfyear" => get_config("nodeinfo","active_users_halfyear"), + "activeMonth" => get_config("nodeinfo","active_users_monthly")); + $nodeinfo["usage"]["localPosts"] = get_config("nodeinfo","local_posts"); + $nodeinfo["usage"]["localComments"] = get_config("nodeinfo","local_comments"); + + header('Content-type: application/json; charset=utf-8'); + echo json_encode($nodeinfo, true); + exit; +} + +function nodeinfo_plugin_enabled($plugin) { + $r = q("SELECT * FROM `addon` WHERE `installed` = 1 AND `name` = '%s'", $plugin); + return((bool)(count($r) > 0)); +} + +function nodeinfo_cron() { + if (!get_config("system", "nodeinfo")) + return; + + $last = get_config('nodeinfo','last_calucation'); + + if($last) { + // Calculate every 24 hours + $next = $last + (24 * 60 * 60); + if($next > time()) { + logger("calculation intervall not reached"); + return; + } + } + logger("cron_start"); + + $users = q("SELECT profile.*, `user`.`login_date`, `lastitem`.`lastitem_date` + FROM (SELECT MAX(`item`.`changed`) as `lastitem_date`, `item`.`uid` + FROM `item` + WHERE `item`.`type` = 'wall' + GROUP BY `item`.`uid`) AS `lastitem` + RIGHT OUTER JOIN `user` ON `user`.`uid` = `lastitem`.`uid`, `contact`, `profile` + WHERE + `user`.`uid` = `contact`.`uid` AND `profile`.`uid` = `user`.`uid` + AND `profile`.`is-default` AND (`profile`.`publish` OR `profile`.`net-publish`) + AND `user`.`verified` AND `contact`.`self` + AND NOT `user`.`blocked` + AND NOT `user`.`account_removed` + AND NOT `user`.`account_expired`"); + + if (is_array($users)) { + $total_users = count($users); + $active_users_halfyear = 0; + $active_users_monthly = 0; + + $halfyear = time() - (180 * 24 * 60 * 60); + $month = time() - (30 * 24 * 60 * 60); + + foreach ($users AS $user) { + if ((strtotime($user['login_date']) > $halfyear) OR + (strtotime($user['lastitem_date']) > $halfyear)) + ++$active_users_halfyear; + + if ((strtotime($user['login_date']) > $month) OR + (strtotime($user['lastitem_date']) > $month)) + ++$active_users_monthly; + + } + set_config('nodeinfo','total_users', $total_users); + logger("total_users: ".$total_users, LOGGER_DEBUG); + + set_config('nodeinfo','active_users_halfyear', $active_users_halfyear); + set_config('nodeinfo','active_users_monthly', $active_users_monthly); + } + + //$posts = q("SELECT COUNT(*) AS local_posts FROM `item` WHERE `wall` AND `uid` != 0 AND `id` = `parent` AND left(body, 6) != '[share'"); + $posts = q("SELECT COUNT(*) AS `local_posts` FROM `item` + INNER JOIN `contact` ON `contact`.`id` = `item`.`contact-id` + WHERE `contact`.`self` and `item`.`id` = `item`.`parent` AND left(body, 6) != '[share' AND `item`.`network` IN ('%s', '%s', '%s')", + dbesc(NETWORK_OSTATUS), dbesc(NETWORK_DIASPORA), dbesc(NETWORK_DFRN)); + + if (!is_array($posts)) + $local_posts = -1; + else + $local_posts = $posts[0]["local_posts"]; + + set_config('nodeinfo','local_posts', $local_posts); + + logger("local_posts: ".$local_posts, LOGGER_DEBUG); + + $posts = q("SELECT COUNT(*) AS `local_comments` FROM `item` + INNER JOIN `contact` ON `contact`.`id` = `item`.`contact-id` + WHERE `contact`.`self` and `item`.`id` != `item`.`parent` AND `item`.`network` IN ('%s', '%s', '%s')", + dbesc(NETWORK_OSTATUS), dbesc(NETWORK_DIASPORA), dbesc(NETWORK_DFRN)); + + if (!is_array($posts)) + $local_comments = -1; + else + $local_comments = $posts[0]["local_comments"]; + + set_config('nodeinfo','local_comments', $local_comments); + + // Now trying to register + //$url = "http://the-federation.info/register/".$a->get_hostname(); + //logger('nodeinfo_cron: registering url: '.$url, LOGGER_DEBUG); + //$ret = fetch_url($url); + //logger('nodeinfo_cron: registering answer: '.$ret, LOGGER_DEBUG); + + logger("cron_end"); + set_config('nodeinfo','last_calucation', time()); +} + +?> From 6aeb4c0ad70b7f20cc39aaec26e69a06861bb773 Mon Sep 17 00:00:00 2001 From: Michael Vogel Date: Mon, 10 Aug 2015 21:54:57 +0200 Subject: [PATCH 2/7] Corrected the output --- mod/_well_known.php | 2 +- mod/nodeinfo.php | 18 ++++++++++-------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/mod/_well_known.php b/mod/_well_known.php index 1271e12f4..33070a1ec 100644 --- a/mod/_well_known.php +++ b/mod/_well_known.php @@ -61,6 +61,6 @@ function wk_social_relay(&$a) { "tags" => $taglist); header('Content-type: application/json; charset=utf-8'); - echo json_encode($relay, true); + echo json_encode($relay, JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES); exit; } diff --git a/mod/nodeinfo.php b/mod/nodeinfo.php index bf1d4ef3e..065f33eb1 100644 --- a/mod/nodeinfo.php +++ b/mod/nodeinfo.php @@ -12,7 +12,7 @@ function nodeinfo_wellknown(&$a) { "href" => $a->get_baseurl()."/nodeinfo/1.0")); header('Content-type: application/json; charset=utf-8'); - echo json_encode($nodeinfo, true); + echo json_encode($nodeinfo, JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES); exit; } @@ -72,7 +72,7 @@ function nodeinfo_init(&$a){ if (nodeinfo_plugin_enabled("fbpost") OR nodeinfo_plugin_enabled("buffer")) $nodeinfo["services"][] = "facebook"; - $nodeinfo["services"][] = " friendica"; + $nodeinfo["services"][] = "friendica"; if (nodeinfo_plugin_enabled("statusnet") OR !get_config("system","ostatus_disabled")) $nodeinfo["services"][] = "gnusocial"; @@ -107,14 +107,16 @@ function nodeinfo_init(&$a){ $nodeinfo["openRegistrations"] = ($a->config['register_policy'] != 0); $nodeinfo["usage"] = array(); - $nodeinfo["usage"]["users"] = array("total" => get_config("nodeinfo","total_users"), - "activeHalfyear" => get_config("nodeinfo","active_users_halfyear"), - "activeMonth" => get_config("nodeinfo","active_users_monthly")); - $nodeinfo["usage"]["localPosts"] = get_config("nodeinfo","local_posts"); - $nodeinfo["usage"]["localComments"] = get_config("nodeinfo","local_comments"); + $nodeinfo["usage"]["users"] = array("total" => (int)get_config("nodeinfo","total_users"), + "activeHalfyear" => (int)get_config("nodeinfo","active_users_halfyear"), + "activeMonth" => (int)get_config("nodeinfo","active_users_monthly")); + $nodeinfo["usage"]["localPosts"] = (int)get_config("nodeinfo","local_posts"); + $nodeinfo["usage"]["localComments"] = (int)get_config("nodeinfo","local_comments"); + + $nodeinfo["usage"]["metadata"] = array(); header('Content-type: application/json; charset=utf-8'); - echo json_encode($nodeinfo, true); + echo json_encode($nodeinfo, JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES); exit; } From e60456fb6644510506d8852fa796bb32cf1f3331 Mon Sep 17 00:00:00 2001 From: Michael Vogel Date: Mon, 10 Aug 2015 23:11:07 +0200 Subject: [PATCH 3/7] Metadata should be an object. --- mod/nodeinfo.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mod/nodeinfo.php b/mod/nodeinfo.php index 065f33eb1..f9211fe9e 100644 --- a/mod/nodeinfo.php +++ b/mod/nodeinfo.php @@ -113,7 +113,7 @@ function nodeinfo_init(&$a){ $nodeinfo["usage"]["localPosts"] = (int)get_config("nodeinfo","local_posts"); $nodeinfo["usage"]["localComments"] = (int)get_config("nodeinfo","local_comments"); - $nodeinfo["usage"]["metadata"] = array(); + $nodeinfo["metadata"] = new stdClass(); header('Content-type: application/json; charset=utf-8'); echo json_encode($nodeinfo, JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES); From 986eee48acee77b3b08f9a1483d8a04692aef2aa Mon Sep 17 00:00:00 2001 From: Michael Vogel Date: Tue, 11 Aug 2015 00:37:27 +0200 Subject: [PATCH 4/7] Some corrections in the addon names --- mod/nodeinfo.php | 37 +++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/mod/nodeinfo.php b/mod/nodeinfo.php index f9211fe9e..0a877e023 100644 --- a/mod/nodeinfo.php +++ b/mod/nodeinfo.php @@ -50,10 +50,11 @@ function nodeinfo_init(&$a){ $nodeinfo["protocols"]["outbound"][] = "gnusocial"; } - if ($smtp) { - $nodeinfo["protocols"]["inbound"][] = "smtp"; - $nodeinfo["protocols"]["outbound"][] = "smtp"; - } + //if ($smtp) { + // $nodeinfo["protocols"]["inbound"][] = "smtp"; + // $nodeinfo["protocols"]["outbound"][] = "smtp"; + //} + $nodeinfo["services"] = array(); @@ -63,23 +64,27 @@ function nodeinfo_init(&$a){ if (nodeinfo_plugin_enabled("blogger")) $nodeinfo["services"][] = "blogger"; - if (get_config("system","diaspora_enabled")) - $nodeinfo["services"][] = "diaspora"; + //if (get_config("system","diaspora_enabled")) + // $nodeinfo["services"][] = "diaspora"; - if (nodeinfo_plugin_enabled("dreamwidth")) + if (nodeinfo_plugin_enabled("dwpost")) $nodeinfo["services"][] = "dreamwidth"; if (nodeinfo_plugin_enabled("fbpost") OR nodeinfo_plugin_enabled("buffer")) $nodeinfo["services"][] = "facebook"; - $nodeinfo["services"][] = "friendica"; + //$nodeinfo["services"][] = "friendica"; - if (nodeinfo_plugin_enabled("statusnet") OR !get_config("system","ostatus_disabled")) + //if (nodeinfo_plugin_enabled("statusnet") OR !get_config("system","ostatus_disabled")) + if (nodeinfo_plugin_enabled("statusnet")) $nodeinfo["services"][] = "gnusocial"; - if (nodeinfo_plugin_enabled("fpluspost") OR nodeinfo_plugin_enabled("buffer")) + if (nodeinfo_plugin_enabled("gpluspost") OR nodeinfo_plugin_enabled("buffer")) $nodeinfo["services"][] = "google"; + if (nodeinfo_plugin_enabled("ijpost")) + $nodeinfo["services"][] = "insanejournal"; + if (nodeinfo_plugin_enabled("libertree")) $nodeinfo["services"][] = "libertree"; @@ -89,9 +94,17 @@ function nodeinfo_init(&$a){ if (nodeinfo_plugin_enabled("ljpost")) $nodeinfo["services"][] = "livejournal"; + if (nodeinfo_plugin_enabled("buffer")) + $nodeinfo["services"][] = "pinterest"; + + if (nodeinfo_plugin_enabled("posterous")) + $nodeinfo["services"][] = "posterous"; + if (nodeinfo_plugin_enabled("pumpio")) $nodeinfo["services"][] = "pumpio"; + // redmatrix + if ($smtp) $nodeinfo["services"][] = "smtp"; @@ -101,8 +114,8 @@ function nodeinfo_init(&$a){ if (nodeinfo_plugin_enabled("twitter")) $nodeinfo["services"][] = "twitter"; - if (nodeinfo_plugin_enabled("wordpress")) - $nodeinfo["services"][] = "wppost"; + if (nodeinfo_plugin_enabled("wppost")) + $nodeinfo["services"][] = "wordpress"; $nodeinfo["openRegistrations"] = ($a->config['register_policy'] != 0); From c18c598bafa93cf1650f51fb9cbaba3b4ad9cb29 Mon Sep 17 00:00:00 2001 From: Michael Vogel Date: Tue, 11 Aug 2015 10:23:33 +0200 Subject: [PATCH 5/7] Nodeinfo: Include the sitename --- mod/nodeinfo.php | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/mod/nodeinfo.php b/mod/nodeinfo.php index 0a877e023..b4f0428f9 100644 --- a/mod/nodeinfo.php +++ b/mod/nodeinfo.php @@ -126,7 +126,8 @@ function nodeinfo_init(&$a){ $nodeinfo["usage"]["localPosts"] = (int)get_config("nodeinfo","local_posts"); $nodeinfo["usage"]["localComments"] = (int)get_config("nodeinfo","local_comments"); - $nodeinfo["metadata"] = new stdClass(); + //$nodeinfo["metadata"] = new stdClass(); + $nodeinfo["metadata"] = array("nodeName" => $a->config["sitename"]); header('Content-type: application/json; charset=utf-8'); echo json_encode($nodeinfo, JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES); @@ -221,10 +222,10 @@ function nodeinfo_cron() { set_config('nodeinfo','local_comments', $local_comments); // Now trying to register - //$url = "http://the-federation.info/register/".$a->get_hostname(); - //logger('nodeinfo_cron: registering url: '.$url, LOGGER_DEBUG); - //$ret = fetch_url($url); - //logger('nodeinfo_cron: registering answer: '.$ret, LOGGER_DEBUG); + $url = "http://the-federation.info/register/".$a->get_hostname(); + logger('registering url: '.$url, LOGGER_DEBUG); + $ret = fetch_url($url); + logger('registering answer: '.$ret, LOGGER_DEBUG); logger("cron_end"); set_config('nodeinfo','last_calucation', time()); From bf9ab389a29c8ce3b67d7dc7300cc3a95e77d471 Mon Sep 17 00:00:00 2001 From: Michael Vogel Date: Tue, 11 Aug 2015 20:16:53 +0200 Subject: [PATCH 6/7] Just some removed blanks --- mod/network.php | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/mod/network.php b/mod/network.php index 56c0eeb95..a92e0c691 100644 --- a/mod/network.php +++ b/mod/network.php @@ -45,7 +45,7 @@ function network_init(&$a) { else if($sel_groups !== false) { $net_baseurl .= '/' . $sel_groups; } - + if($remember_tab) { // redirect if current selected tab is '/network' and // last selected tab is _not_ '/network?f=&order=comment'. @@ -91,17 +91,17 @@ function network_init(&$a) { else if($sel_nets!==false) { $net_args['nets'] = $sel_nets; } - + if($remember_tab || $remember_net || $remember_group) { $net_args = array_merge($query_array, $net_args); $net_queries = build_querystring($net_args); - + $redir_url = ($net_queries ? $net_baseurl."?".$net_queries : $net_baseurl); - + goaway($a->get_baseurl() . $redir_url); } } - + if(x($_GET['nets']) && $_GET['nets'] === 'all') unset($_GET['nets']); @@ -485,8 +485,8 @@ function network_content(&$a, $update = 0) { 'allow_location' => $a->user['allow_location'], 'default_location' => $a->user['default-location'], 'nickname' => $a->user['nickname'], - 'lockstate'=> ((($group) || ($cid) || ($nets) || (is_array($a->user) && - ((strlen($a->user['allow_cid'])) || (strlen($a->user['allow_gid'])) || + 'lockstate'=> ((($group) || ($cid) || ($nets) || (is_array($a->user) && + ((strlen($a->user['allow_cid'])) || (strlen($a->user['allow_gid'])) || (strlen($a->user['deny_cid'])) || (strlen($a->user['deny_gid']))))) ? 'lock' : 'unlock'), 'default_perms' => get_acl_permissions($a->user), 'acl' => populate_acl((($group || $cid || $nets) ? $def_acl : $a->user), true), @@ -552,8 +552,8 @@ function network_content(&$a, $update = 0) { //$sql_post_table = " INNER JOIN (SELECT DISTINCT(`parent`) FROM `item` WHERE (`contact-id` IN ($contact_str) OR `allow_gid` like '".protect_sprintf('%<'.intval($group).'>%')."') and deleted = 0 ORDER BY `created` DESC) AS `temp1` ON $sql_table.$sql_parent = `temp1`.`parent` "; $sql_extra3 .= " AND `contact-id` IN ($contact_str$contact_str_self) "; - $sql_extra3 .= " AND EXISTS (SELECT id FROM `item` WHERE (`contact-id` IN ($contact_str) - OR `allow_gid` like '".protect_sprintf('%<'.intval($group).'>%')."') and deleted = 0 + $sql_extra3 .= " AND EXISTS (SELECT id FROM `item` WHERE (`contact-id` IN ($contact_str) + OR `allow_gid` like '".protect_sprintf('%<'.intval($group).'>%')."') and deleted = 0 AND parent = $sql_table.$sql_parent) "; $o = replace_macros(get_markup_template("section_title.tpl"),array( From d5f2d9b39a5aab4cb708d2f682430c6f9c5a312c Mon Sep 17 00:00:00 2001 From: Michael Vogel Date: Tue, 11 Aug 2015 23:50:31 +0200 Subject: [PATCH 7/7] Bugfix ... --- mod/nodeinfo.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mod/nodeinfo.php b/mod/nodeinfo.php index b4f0428f9..d19d0fc99 100644 --- a/mod/nodeinfo.php +++ b/mod/nodeinfo.php @@ -140,6 +140,9 @@ function nodeinfo_plugin_enabled($plugin) { } function nodeinfo_cron() { + + $a = get_app(); + if (!get_config("system", "nodeinfo")) return;