Commit 10056a8e authored by David Morley's avatar David Morley

Support all networks

parent f1c80dd7
......@@ -3,6 +3,8 @@ The format is based on [Keep a Changelog] and this project adheres to [Semantic
## [Unreleased]
### Added
- store protocols that pods support
- hide software names you don't want on table/go - leaving in stats for now
### Changed
- add.php test for pod meta like update.php
- use meta table for updating monthly stats not the diasp.org hack
......@@ -13,8 +15,13 @@ The format is based on [Keep a Changelog] and this project adheres to [Semantic
- missing tables.sql item from version 2.5.2
- missing table on tables.sql
- link to osada repo updated
- use any valid nodeinfo pod
- softwares are in config.php now so it is not hardcoded to add and update git repos
- some UI issues with more than 1000 pods listed
- uptime and growth charts per pod to be unlimited timespan
- use dig command vs delv as ecdsa keys are not being detected properly by delv
- stats page human readabe dates/times
- system deleted fix
### Security
## [2.5.2] - 2019-01-29
......
......@@ -46,16 +46,16 @@
},
{
"name": "composer/ca-bundle",
"version": "1.1.3",
"version": "1.1.4",
"source": {
"type": "git",
"url": "https://github.com/composer/ca-bundle.git",
"reference": "8afa52cd417f4ec417b4bfe86b68106538a87660"
"reference": "558f321c52faeb4828c03e7dc0cfe39a09e09a2d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/composer/ca-bundle/zipball/8afa52cd417f4ec417b4bfe86b68106538a87660",
"reference": "8afa52cd417f4ec417b4bfe86b68106538a87660",
"url": "https://api.github.com/repos/composer/ca-bundle/zipball/558f321c52faeb4828c03e7dc0cfe39a09e09a2d",
"reference": "558f321c52faeb4828c03e7dc0cfe39a09e09a2d",
"shasum": ""
},
"require": {
......@@ -98,7 +98,7 @@
"ssl",
"tls"
],
"time": "2018-10-18T06:09:13+00:00"
"time": "2019-01-28T09:30:10+00:00"
},
{
"name": "detectlanguage/detectlanguage",
......@@ -807,16 +807,16 @@
},
{
"name": "symfony/translation",
"version": "v4.2.2",
"version": "v4.2.3",
"source": {
"type": "git",
"url": "https://github.com/symfony/translation.git",
"reference": "939fb792d73f2ce80e6ae9019d205fc480f1c9a0"
"reference": "23fd7aac70d99a17a8e6473a41fec8fab3331050"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/translation/zipball/939fb792d73f2ce80e6ae9019d205fc480f1c9a0",
"reference": "939fb792d73f2ce80e6ae9019d205fc480f1c9a0",
"url": "https://api.github.com/repos/symfony/translation/zipball/23fd7aac70d99a17a8e6473a41fec8fab3331050",
"reference": "23fd7aac70d99a17a8e6473a41fec8fab3331050",
"shasum": ""
},
"require": {
......@@ -876,7 +876,7 @@
],
"description": "Symfony Translation Component",
"homepage": "https://symfony.com",
"time": "2019-01-03T09:07:35+00:00"
"time": "2019-01-27T23:11:39+00:00"
}
],
"packages-dev": [
......
......@@ -49,4 +49,30 @@ return [
//detectlanguage.com api key
'dlkey' => '',
//softwares and git repos we support
'softwares' => [
'diaspora' => ['repo' => 'diaspora/diaspora', 'gitsite' => 'api.github.com', 'gittype' => 'github', 'devbranch' => 'develop'],
'friendica' => ['repo' => 'friendica/friendica', 'gitsite' => 'api.github.com', 'gittype' => 'github', 'devbranch' => 'develop'],
'hubzilla' => ['repo' => 'hubzilla%2fcore', 'gitsite' => 'framagit.org', 'gittype' => 'gitlab', 'devbranch' => 'dev'],
'pleroma' => ['repo' => 'pleroma%2fpleroma', 'gitsite' => 'git.pleroma.social', 'gittype' => 'gitlab', 'devbranch' => 'develop'],
'socialhome' => ['repo' => 'socialhome%2fsocialhome', 'gitsite' => 'git.feneas.org', 'gittype' => 'gitlab', 'devbranch' => ''],
'social-relay' => ['repo' => 'jaywink%2fsocial-relay', 'gitsite' => 'git.feneas.org', 'gittype' => 'gitlab', 'devbranch' => ''],
'writefreely' => ['repo' => 'writeas/writefreely', 'gitsite' => 'api.github.com', 'gittype' => 'github', 'devbranch' => 'develop'],
'ganggo' => ['repo' => 'ganggo%2fganggo', 'gitsite' => 'git.feneas.org', 'gittype' => 'gitlab', 'devbranch' => ''],
'funkwhale' => ['repo' => 'funkwhale%2ffunkwhale', 'gitsite' => 'code.eliotberriot.com', 'gittype' => 'gitlab', 'devbranch' => 'develop'],
'osada' => ['repo' => 'zot%2fosada', 'gitsite' => 'framagit.org', 'gittype' => 'gitlab', 'devbranch' => 'dev'],
'funkwhale' => ['repo' => 'funkwhale%2ffunkwhale', 'gitsite' => 'dev.funkwhale.audio', 'gittype' => 'gitlab', 'devbranch' => 'develop'],
'gnusocial' => ['repo' => 'gnu%2fgnu-social', 'gitsite' => 'git.gnu.io', 'gittype' => 'gitlab', 'devbranch' => 'nightly'],
'pixelfed' => ['repo' => 'pixelfed/pixelfed', 'gitsite' => 'api.github.com', 'gittype' => 'github', 'devbranch' => 'dev'],
'wordpress' => ['repo' => 'Wordpress/Wordpress', 'gitsite' => 'api.github.com', 'gittype' => 'github', 'devbranch' => ''],
'misskey' => ['repo' => 'syuilo/misskey', 'gitsite' => 'api.github.com', 'gittype' => 'github', 'devbranch' => 'develop'],
'speechmore' => ['repo' => 'speechmore%2fspeechmore', 'gitsite' => 'gitlab.fancy.org.uk', 'gittype' => 'gitlab', 'devbranch' => ''],
'peertube' => ['repo' => 'Chocobozzz/PeerTube', 'gitsite' => 'api.github.com', 'gittype' => 'github', 'devbranch' => 'develop'],
'plume' => ['repo' => 'Plume-org/Plume', 'gitsite' => 'api.github.com', 'gittype' => 'github', 'devbranch' => ''],
'rustodon' => ['repo' => 'rustodon/rustodon', 'gitsite' => 'api.github.com', 'gittype' => 'github', 'devbranch' => ''],
],
//hidden software word strings from table view - %(one)% OR %(one|two|three)%
'hidden-softwares' => '%(relay)%',
];
......@@ -173,7 +173,7 @@ a {
text-decoration: none;
transition: background-color .3s;
cursor: pointer;
width: 170px;
width: 200px;
height: 30px;
}
......@@ -225,7 +225,7 @@ a {
.loadingtable {
width: 100%;
height: 100%;
background: #fff;
background-color: rgba(78,137,164,.8);
position: fixed;
margin: 0;
padding: 0;
......@@ -233,20 +233,26 @@ a {
}
.signal {
border: 5px solid #333;
border-radius: 30px;
height: 30px;
left: 20%;
margin: -15px 0 0 -15px;
border: 6px solid #ffffff;
border-radius: 50px;
height: 40px;
left: 5%;
margin: -20px 0 0 -20px;
opacity: 0;
position: absolute;
top: 20%;
width: 30px;
animation: pulsate 1s ease-out;
top: 24%;
width: 40px;
animation: pulsate 2s ease-in-out;
animation-iteration-count: infinite;
}
.loadingmessage {
left: 1%;
position: absolute;
top: 19%;
color: #ffffff;
}
@keyframes pulsate {
0% {
transform: scale(.1);
......@@ -286,3 +292,7 @@ a {
}
.tooltip { pointer-events: none; }
.navbar-custom {
background-color: rgba(78,137,164,.4);
}
ALTER TABLE pods ADD protocols jsonb;
\ No newline at end of file
......@@ -32,6 +32,7 @@ CREATE TABLE pods (
latency smallint,
service_xmpp boolean,
services jsonb,
protocols jsonb,
token text,
publickey text,
tokenexpire timestamp,
......
......@@ -15,31 +15,15 @@ if (!is_cli()) {
exit;
}
$softwares = [
'diaspora' => ['repo' => 'diaspora/diaspora', 'gitsite' => 'api.github.com', 'gittype' => 'github', 'devbranch' => 'develop'],
'friendica' => ['repo' => 'friendica/friendica', 'gitsite' => 'api.github.com', 'gittype' => 'github', 'devbranch' => 'develop'],
'hubzilla' => ['repo' => 'hubzilla%2fcore', 'gitsite' => 'framagit.org', 'gittype' => 'gitlab', 'devbranch' => 'dev'],
'pleroma' => ['repo' => 'pleroma%2fpleroma', 'gitsite' => 'git.pleroma.social', 'gittype' => 'gitlab', 'devbranch' => 'develop'],
'socialhome' => ['repo' => 'jaywink/socialhome', 'gitsite' => 'api.github.com', 'gittype' => 'github', 'devbranch' => ''],
'social-relay' => ['repo' => 'jaywink/social-relay', 'gitsite' => 'api.github.com', 'gittype' => 'github', 'devbranch' => ''],
'writefreely' => ['repo' => 'writeas/writefreely', 'gitsite' => 'api.github.com', 'gittype' => 'github', 'devbranch' => 'develop'],
'ganggo' => ['repo' => 'ganggo%2fganggo', 'gitsite' => 'git.feneas.org', 'gittype' => 'gitlab', 'devbranch' => ''],
'funkwhale' => ['repo' => 'funkwhale%2ffunkwhale', 'gitsite' => 'code.eliotberriot.com', 'gittype' => 'gitlab', 'devbranch' => 'develop'],
'osada' => ['repo' => 'zot%2fosada', 'gitsite' => 'framagit.org', 'gittype' => 'gitlab', 'devbranch' => 'dev'],
];
$opts = [
'http' => ['method' => 'GET', 'header' => ['User-Agent: Poduptime']],
];
$softwares = c('softwares');
foreach ($softwares as $software => $details) {
if ($details['gittype'] === 'github') {
$context = stream_context_create($opts);
$releasejson = json_decode(file_get_contents('https://' . $details['gitsite'] . '/repos/' . $details['repo'] . '/releases/latest', false, $context));
$rjson = curl('https://' . $details['gitsite'] . '/repos/' . $details['repo'] . '/releases/latest');
$releasejson = json_decode($rjson['body'] ?: '');
if ($details['devbranch']) {
$commitjson = json_decode(file_get_contents('https://' . $details['gitsite'] . '/repos/' . $details['repo'] . '/commits/' . $details['devbranch'], false, $context));
} else {
$commitjson = '';
$cjson = curl('https://' . $details['gitsite'] . '/repos/' . $details['repo'] . '/commits/' . $details['devbranch']);
$commitjson = json_decode($cjson['body'] ?: '');
}
if ($masterversion = $releasejson->tag_name ? str_replace('v', '', $releasejson->tag_name) : '') {
try {
......@@ -58,12 +42,11 @@ foreach ($softwares as $software => $details) {
}
}
} elseif ($details['gittype'] === 'gitlab') {
$context = stream_context_create($opts);
$releasejson = json_decode(file_get_contents('https://' . $details['gitsite'] . '/api/v4/projects/' . $details['repo'] . '/repository/tags', false, $context));
$rjson = curl('https://' . $details['gitsite'] . '/api/v4/projects/' . $details['repo'] . '/repository/tags');
$releasejson = json_decode($rjson['body'] ?: '');
if ($details['devbranch']) {
$commitjson = json_decode(file_get_contents('https://' . $details['gitsite'] . '/api/v4/projects/' . $details['repo'] . '/repository/commits/' . $details['devbranch'], false, $context));
} else {
$commitjson = '';
$cjson = curl('https://' . $details['gitsite'] . '/api/v4/projects/' . $details['repo'] . '/repository/commits/' . $details['devbranch']);
$commitjson = json_decode($cjson['body'] ?: '');
}
if ($masterversion = $releasejson[0]->name ? str_replace('v', '', $releasejson[0]->name) : '') {
try {
......
......@@ -35,11 +35,7 @@ $federationpods = curl('https://the-federation.info/graphql?query=%7Bnodes%7Bhos
if ($pods = json_decode($federationpods['body'] ?: '', true)) {
foreach ($pods['data']['nodes'] ?? [] as $poddata) {
$protocols = array_column($poddata['protocols'] ?? [], 'name');
//limiting to diaspora compatible for now
if (in_array('diaspora', $protocols, true)) {
$foundpods[] = strtolower(preg_replace('(^https?://)', '', $poddata['host']));
}
$foundpods[] = strtolower(preg_replace('(^https?://)', '', $poddata['host']));
}
}
......
......@@ -148,7 +148,7 @@ foreach ($pods as $pod) {
preg_match_all('((?:\d(.|-)?)+(\.)\d+\.*)', $version, $sversion);
$shortversion = $sversion[0][0] ?? '0.0.0.0';
$signup = ($jsonssl->openRegistrations ?? false) === true;
$softwarename = $jsonssl->software->name ?? 'unknown';
$softwarename = strtolower($jsonssl->software->name) ?? 'unknown';
$name = $jsonssl->metadata->nodeName ?? $softwarename;
$total_users = $jsonssl->usage->users->total ?? 0;
$active_users_halfyear = $jsonssl->usage->users->activeHalfyear ?? 0;
......@@ -161,6 +161,9 @@ foreach ($pods as $pod) {
if (is_array($jsonssl->services->outbound)) {
$services = json_encode($jsonssl->services->outbound);
}
if (is_array($jsonssl->protocols)) {
$protocols = json_encode($jsonssl->protocols);
}
}
try {
......@@ -177,7 +180,8 @@ foreach ($pods as $pod) {
if ($write) {
R::store($c);
} else {
echo $c;
echo 'Data not saved, testing only';
echo $newline;
}
} catch (\RedBeanPHP\RedException $e) {
debug('Error in SQL query: ' . sprintf($e->getMessage()));
......@@ -291,7 +295,8 @@ foreach ($pods as $pod) {
if ($write) {
R::store($c);
} else {
echo $c;
echo 'Data not saved, testing only';
echo $newline;
}
} catch (\RedBeanPHP\RedException $e) {
debug('Error in SQL query: ' . sprintf($e->getMessage()));
......@@ -327,7 +332,7 @@ foreach ($pods as $pod) {
debug('DNSSEC', $dnssec);
// todo: Temporary workaround (see https://github.com/akalongman/php-ip-tools/issues/8)
if (Ip::isValid($ip) && Ip::isRemote($ip)) {
if (Ip::isValid($ip) && Ip::isRemote($ip) && $ip != '0.0.0.0') {
$geo = $reader->city($ip);
$countryname = ($geo->country->name ?? null) ?: null;
$country = ($geo->country->isoCode ?? null) ?: null;
......@@ -385,13 +390,16 @@ foreach ($pods as $pod) {
if ($score > 100) {
$score = 100;
} elseif ($score < 1) {
}
if ($score < 1) {
$weightedscore = 0;
} elseif ($score < -6000) {
}
if ($score < -6000) {
$status = PodStatus::SYSTEM_DELETED;
}
debug('Score', $score);
debug('Status', $status);
debug('Weighted Score', $weightedscore);
try {
......@@ -430,6 +438,7 @@ foreach ($pods as $pod) {
$p['comment_counts'] = $comment_counts;
$p['service_xmpp'] = $service_xmpp;
$p['services'] = $services;
$p['protocols'] = $protocols;
$p['softwarename'] = $softwarename;
}
......
......@@ -17,6 +17,8 @@ $_software = $_GET['software'] ?? '';
require_once __DIR__ . '/boot.php';
$hiddensoftwares = c('hidden-softwares');
try {
if ($_domain) {
$click = 'manualclick';
......@@ -32,9 +34,10 @@ try {
AND monthsmonitored > 1
AND softwarename = ?
AND status = ?
AND softwarename NOT SIMILAR TO ?
ORDER BY random()
LIMIT 1
', [$_software, PodStatus::UP]);
', [$_software, PodStatus::UP, $hiddensoftwares]);
$domain || die('no domains exist');
} else {
$click = 'autoclick';
......@@ -46,9 +49,10 @@ try {
AND monthsmonitored > 2
AND pods.masterversion = shortversion
AND status = ?
AND softwarename NOT SIMILAR TO ?
ORDER BY random()
LIMIT 1
', [PodStatus::UP]);
', [PodStatus::UP, $hiddensoftwares]);
$domain || die('no domains exist');
}
......
......@@ -28,8 +28,8 @@ $fullview = false;
<head>
<meta charset="utf-8">
<title>Open Source Social Network Pod Uptime Status</title>
<meta name="keywords" content="diaspora, <?php echo $input ?>, federated pods, <?php echo $_SERVER['HTTP_HOST'] ?>, friendica, hubzilla, open source social, open source social network"/>
<meta name="description" content="Diaspora Pod <?php echo $input ?> Live Status. Find a Diaspora pod to sign up for, rate pods, find one close to you!"/>
<meta name="keywords" content="diaspora, <?php echo $input ?>, federated pods, <?php echo $_SERVER['HTTP_HOST'] ?>, fediverse, federated network, friendica, hubzilla, open source social, open source social network"/>
<meta name="description" content="Federated Pod <?php echo $input ?> Live Status. Find a Federated Network pod to sign up for, rate pods, find one close to you!"/>
<link rel="stylesheet" href="node_modules/bootstrap/dist/css/bootstrap.min.css">
<link rel="stylesheet" href="css/poduptime.css"/>
<link rel="stylesheet" href="node_modules/ion-rangeslider/css/ion.rangeSlider.css"/>
......@@ -37,10 +37,11 @@ $fullview = false;
<link rel="stylesheet" href="node_modules/featherlight/release/featherlight.min.css"/>
<link rel="stylesheet" href="node_modules/tablesorter/dist/css/theme.bootstrap_4.min.css"/>
<link rel="stylesheet" href="node_modules/@fortawesome/fontawesome-free/css/all.min.css"/>
<link rel="stylesheet" href="node_modules/fork-awesome/css/fork-awesome.min.css"/>
<meta property="og:url" content="https://<?php echo $_SERVER['HTTP_HOST'] ?>/<?php echo $input ?>"/>
<meta property="og:title" content="Social Network Pod <?php echo $input ?> Finder"/>
<meta property="og:type" content="website"/>
<meta property="og:description" content="Diaspora Pod <?php echo $input ?> Live Status. Find a Diaspora pod to sign up for, rate pods, find one close to you!"/>
<meta property="og:description" content="Federated Network Pod <?php echo $input ?> Live Status. Find a Federated Network pod to sign up for, rate pods, find one close to you!"/>
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=yes">
<meta http-equiv="x-ua-compatible" content="ie=edge">
</head>
......@@ -57,9 +58,9 @@ $navs = [
'links' => [
['text' => 'Git', 'href' => 'https://git.feneas.org/diasporg/Poduptime', 'active' => false],
['text' => 'Contact', 'href' => 'https://dia.so/support', 'active' => false],
['text' => 'Wiki', 'href' => 'https://git.feneas.org/diasporg/Poduptime/wikis/home', 'active' => false],
['text' => 'API', 'href' => 'https://git.feneas.org/diasporg/Poduptime/wikis/API', 'active' => false],
['text' => 'How to host a pod', 'href' => 'https://fediverse.party/', 'active' => false],
['text' => 'Wiki/API', 'href' => 'https://git.feneas.org/diasporg/Poduptime/wikis/home', 'active' => false],
['text' => 'More about the Fediverse', 'href' => 'https://fediverse.party', 'active' => false],
['text' => 'Federated Networks Association', 'href' => 'https://feneas.org', 'active' => false],
],
];
?>
......@@ -69,7 +70,7 @@ $navs = [
<div class="row">
<div class="col-sm-8 col-md-7 py-4">
<h4 class="text-black">About</h4>
<p class="text-white">Poduptime helps you find a diaspora, friendica, hubzilla or socialhome pod to use and join the federated social network.</p>
<p class="text-white">Poduptime helps you find a pod to use and join the Fediverse (Federated Network). </p>
<ul class="navbar-nav">
<?php
foreach ($navs['links'] as $nav_item) {
......@@ -107,7 +108,7 @@ $navs = [
<a href="/" class="navbar-brand d-flex align-items-center">
<strong>Poduptime</strong>
</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarHeader" aria-controls="navbarHeader" aria-expanded="false" aria-label="Toggle navigation">
<button class="navbar-toggler navbar-custom" type="button" data-toggle="collapse" data-target="#navbarHeader" aria-controls="navbarHeader" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
</div>
......
......@@ -29,7 +29,7 @@ $table
.tablesorterPager(pagerOptions);
$(document).ready(function () {
$('.columnssimple').on('click', function () {
$('table').trigger('refreshColumnSelector', true);
$('#colSelect1').prop('checked', false);
......@@ -41,7 +41,7 @@ $(document).ready(function () {
$('table').trigger('filterReset');
});
$('.columnsadvanced').on('click', function () {
$('table').trigger('refreshColumnSelector', ['columns', [2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13, 14, 15, 16, 17, 18, 21, 22, 28]]);
$('table').trigger('refreshColumnSelector', ['columns', [2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13, 14, 15, 16, 17, 19, 22, 23, 24]]);
$('#colSelect1').prop('checked', false);
$('.columnSelectorWrapper').show().css('display', 'inline-block');
$('.columnssimple').show().css('display', 'inline-block');
......@@ -57,15 +57,15 @@ $(document).ready(function () {
$('table tbody').append(html);
$('table').trigger('update', [true]);
var columns = [];
columns[7] = 'Yes';
columns[8] = 'Yes';
if (input) {
columns[0] = input;
columns[7] = '';
columns[8] = '';
}
$('table').trigger('search', [columns]);
$('.pagerhidden').delay(900).show(200);
$('.pagerhidden').delay(300).show(800);
$('[data-toggle="tooltip"]').tooltip();
$('.loadingtable').delay(300).hide(100);
$('.loadingtable').delay(300).hide(300);
});
$('#colSelect1').prop('checked', false);
});
......@@ -115,6 +115,7 @@ function curl(string $url, bool $follow = false): array
curl_setopt($chss, CURLOPT_FAILONERROR, true);
curl_setopt($chss, CURLOPT_CERTINFO, true);
curl_setopt($chss, CURLOPT_FOLLOWLOCATION, $follow);
curl_setopt($chss, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 5.1; rv:31.0) Gecko/20100101 Firefox/31.0');
curl_setopt($chss, CURLOPT_CAINFO, c('cafullpath'));
$data = [
'body' => curl_exec($chss),
......@@ -167,7 +168,7 @@ function getWebsiteLanguageSnippetFromUrl(string $url): ?string
}
}
return $snippet;
return filter_var($snippet, FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_HIGH);
}
/**
......
......@@ -32,7 +32,7 @@ try {
die('Error in SQL query: ' . $e->getMessage());
}
?>
<div class="chart-container p-1" style="height:400px; width:700px">
<div class="chart-container p-1 table-responsive" style="height:400px; width:700px">
<canvas id="pod_chart_counts"></canvas>
</div>
<script>
......
......@@ -31,7 +31,7 @@ try {
die('Error in SQL query: ' . $e->getMessage());
}
?>
<div class="chart-container mb-6 p-1" style="height:400px; width:700px">
<div class="chart-container mb-6 p-1 table-responsive" style="height:400px; width:700px">
<canvas id="pod_chart_responses"></canvas>
</div>
<script>
......
......@@ -50,6 +50,7 @@ $country_code = $_SERVER['HTTP_CF_IPCOUNTRY'] ?? '';
<option value="60">60</option>
<option value="120">120</option>
<option value="240">240</option>
<option value="500">500</option>
<option value="all">All</option>
</select>
</div>
......@@ -57,6 +58,7 @@ $country_code = $_SERVER['HTTP_CF_IPCOUNTRY'] ?? '';
<div class="table-responsive">
<div class="loadingtable">
<div class="loadingmessage">Loading Table</div>
<div class="signal"></div>
</div>
<table class="table table-bordered table-sm tablesorter table-hover tfont">
......@@ -66,6 +68,7 @@ $country_code = $_SERVER['HTTP_CF_IPCOUNTRY'] ?? '';
<th class="columnSelector-false"><div>Name</div></th>
<th class="columnSelector-false"><div data-toggle="tooltip" title="Version of software this pod runs">Version</div></th>
<th class="columnSelector-false filter-select" data-priority="3"><div data-toggle="tooltip" title="Type of software this pod runs">Software</div></th>
<th class="filter-match" data-priority="4"><div data-toggle="tooltip" title="Protocols this pod supports.">Protocols</div></th>
<th data-priority="1"><div data-toggle="tooltip" title="Percent of the time the pod is online.">Uptime</div></th>
<th class="columnSelector-false filter-select"><div data-toggle="tooltip" title="Does this pod offer ipv6 connection.">IPv6</div></th>
<th class="columnSelector-false"><div data-toggle="tooltip" title="Average connection latency time in ms from Los Angeles.">Latency</div></th>
......
......@@ -71,23 +71,25 @@ try {
($pod['service_xmpp'] ?? false) && $services[] = 'xmpp';
$services_list = [
'facebook' => ['img' => 'node_modules/simple-icons/icons/facebook.svg', 'title' => 'Publish to Facebook'],
'twitter' => ['img' => 'node_modules/simple-icons/icons/twitter.svg', 'title' => 'Publish to Twitter'],
'tumblr' => ['img' => 'node_modules/simple-icons/icons/tumblr.svg', 'title' => 'Publish to Tumblr'],
'wordpress' => ['img' => 'node_modules/simple-icons/icons/wordpress.svg', 'title' => 'Publish to WordPress'],
'xmpp' => ['img' => 'images/xmpp.svg', 'title' => 'XMPP chat server'],
'appnet' => ['img' => 'images/app-net.svg', 'title' => 'Publish to App.net'],
'atom1.0' => ['img' => 'node_modules/simple-icons/icons/atom.svg', 'title' => 'Publish to Atom'],
'rss2.0' => ['img' => 'node_modules/simple-icons/icons/atom.svg', 'title' => 'Publish to RSS'],
'blogger' => ['img' => 'node_modules/simple-icons/icons/blogger.svg', 'title' => 'Publish to Blogger'],
'gnusocial' => ['img' => 'node_modules/simple-icons/icons/gnusocial.svg', 'title' => 'Publish to GNUSocial'],
'google' => ['img' => 'node_modules/simple-icons/icons/google.svg', 'title' => 'Publish to Google+'],
'libertree' => ['img' => 'images/libertree.svg', 'title' => 'Publish to Libertree'],
'medium' => ['img' => 'node_modules/simple-icons/icons/medium.svg', 'title' => 'Publish to Medium'],
'linkedin' => ['img' => 'node_modules/simple-icons/icons/linkedin.svg', 'title' => 'Publish to LinkedIn'],
'livejournal' => ['img' => 'node_modules/simple-icons/icons/livejournal.svg', 'title' => 'Publish to Live Journal'],
'pinterest' => ['img' => 'node_modules/simple-icons/icons/pinterest.svg', 'title' => 'Publish to Pinterest'],
'pumpio' => ['img' => 'images/pumpio.svg', 'title' => 'Publish to Pump.io'],
'facebook' => ['class' => 'fa fa-facebook', 'title' => 'Publish to Facebook'],
'twitter' => ['class' => 'fa fa-twitter', 'title' => 'Publish to Twitter'],
'tumblr' => ['class' => 'fa fa-tumblr', 'title' => 'Publish to Tumblr'],
'wordpress' => ['class' => 'fa fa-wordpress', 'title' => 'Publish to WordPress'],
'xmpp' => ['class' => 'fa fa-xmpp', 'title' => 'XMPP chat server'],
'atom1.0' => ['class' => 'fa fa-rss-square', 'title' => 'Publish to Atom'],
'rss2.0' => ['class' => 'fa fa-rss', 'title' => 'Publish to RSS'],
'blogger' => ['class' => 'fa fa-bold', 'title' => 'Publish to Blogger'],
'gnusocial' => ['class' => 'fa fa-gnu-social', 'title' => 'Publish to GNUSocial'],
'google' => ['class' => 'fa fa-google-plus', 'title' => 'Publish to Google+'],
'libertree' => ['class' => 'fa fa-tree', 'title' => 'Publish to Libertree'],
'medium' => ['class' => 'fa fa-medium', 'title' => 'Publish to Medium'],
'linkedin' => ['class' => 'fa fa-linkedin', 'title' => 'Publish to LinkedIn'],
'livejournal' => ['class' => 'fa fa-book', 'title' => 'Publish to Live Journal'],
'pinterest' => ['class' => 'fa fa-pinterest', 'title' => 'Publish to Pinterest'],
'friendica' => ['class' => 'fa fa-friendica', 'title' => 'Publish to Friendica'],
'mastodon' => ['class' => 'fa fa-mastodon', 'title' => 'Publish to Mastodon'],
'smtp' => ['class' => 'fa fa-envelope-o', 'title' => 'smtp'],
'pumpio' => ['class' => 'fa fa-chevron-circle-right', 'title' => 'Publish to Pump.io'],
];
foreach ($services as $service) {
......@@ -97,9 +99,10 @@ try {
}
$feat .= sprintf(
'<div class="smlogo mr-sm-1"><img src="%1$s" data-toggle="tooltip" title="%2$s" height="16" width="16"/></div>',
$services_list[$service]['img'],
$services_list[$service]['title']
'<div class="smlogo mr-sm-1 %1$s" data-toggle="tooltip" title="%2$s"><div class="hidden">%3$s</div></div>',
$services_list[$service]['class'],
$services_list[$service]['title'],
$service
);
}
......
<div class="container">
<div class="row">
<div class="col-xs-12 col-sm-6 col-lg-4 text-center">Users by network<br>
<canvas id="total_network_users" width="300" height="350"></canvas>
<div class="row justify-content-center">
<div class="col-auto text-center">Users by network<br>
<canvas id="total_network_users"></canvas>
</div>
<div class="col-xs-12 col-sm-6 col-lg-4 text-center">Pods by network<br>
<canvas id="total_network_pods" width="300" height="350"></canvas>
<div class="col-auto text-center">Pods by network<br>
<canvas id="total_network_pods"></canvas>
</div>
<div class="col-xs-12 col-sm-6 col-lg-4 text-center">Uptime by network<br>
<canvas id="total_network_uptime" width="300" height="350"></canvas>
<div class="col-auto text-center">Uptime by network<br>
<canvas id="total_network_uptime"></canvas>
</div>
</div>
<br>
......@@ -24,4 +24,17 @@
</tbody>
</table>
</div>
<div class="table-responsive">
<table class="d-flex justify-content-center">
<tbody>
<tr>
<td>
<div class="col text-center">Pods Checked Per Month<br>
<canvas id="pod_growth" style="height:300px; width:900px"></canvas>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
......@@ -29,7 +29,7 @@ try {
}
try {
$check_totals = R::getAll("
$check_total_users = R::getAll("
SELECT
to_char(date_checked, 'yyyy-mm') AS yymm,
total_users AS users
......@@ -41,8 +41,22 @@ try {
die('Error in SQL query: ' . $e->getMessage());
}
try {
$check_total_pods = R::getAll("
SELECT
to_char(date_checked, 'yyyy-mm') AS yymm,
total_pods AS pods
FROM monthlystats
GROUP BY yymm, pods
ORDER BY yymm
");
} catch (\RedBeanPHP\RedException $e) {
die('Error in SQL query: ' . $e->getMessage());
}
?>
<script>
/**
* Add a new pie chart for the passed data.
*
......@@ -50,19 +64,52 @@ try {
* @param data Data to display on the chart.
*/
function addPieChart(id, data) {
var intToRGB = function(value, alpha, max) {
var valueAsPercentageOfMax = value / max;
// actual max is 16777215 but represnts white so we will take a max that is
// below this to avoid white
var MAX_RGB_INT = 16600000;
var valueFromMaxRgbInt = Math.floor(MAX_RGB_INT * valueAsPercentageOfMax);
//credit to https://stackoverflow.com/a/2262117/2737978 for the idea of how to implement
var blue = Math.floor(valueFromMaxRgbInt % 256);
var green = Math.floor(valueFromMaxRgbInt / 256 % 256);
var red = Math.floor(valueFromMaxRgbInt / 256 / 256 % 256);
return "rgba(" + red + "," + green + "," + blue + "," + alpha + ")";
}
var MAX = data.length;
var backgroundColors = data.map(function(item) {
return intToRGB(item, 0.8, MAX);
});
var borderColors = data.map(function(item) {
return intToRGB(item, 1, MAX);
});
new Chart(document.getElementById(id), {
type: "pie",
data: {
labels: <?php echo json_encode(array_column($totals, 'softwarename')); ?>,
datasets: [{
data: data,
backgroundColor: ["#C8412E", "#36A2EB", "#FFCE56", "#419641", "#A569BD", "#EB984E", "#AC8416", "#4F8AAA", "#19FFE2", "#87FE12", "#F3BB88"],
hoverBackgroundColor: ["#C8887B", "#36A2AD", "#FFCE10", "#419615", "#A569AA", "#EB980A", "#AC8456", "#4F8BAB", "#19FFE9", "#87FE32", "#F3FB88"]
backgroundColor: backgroundColors,
borderColor: borderColors,
borderWidth: 1
}]
},
options: {
responsive: false,
maintainAspectRatio: false
responsive: true,
maintainAspectRatio: true,
legend: {
display: false,
labels: {
fontSize: 9,
boxWidth: 4
}
}