Last active
April 19, 2017 16:01
-
-
Save Wack0/b5661777c76e79785c2187fafe331c93 to your computer and use it in GitHub Desktop.
CLI Mastodon network stats script. Uses instances.mastodon.xyz. Updates every 60 seconds.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
// This class adapted from: https://www.if-not-true-then-false.com/2010/php-class-for-coloring-php-command-line-cli-scripts-output-php-output-colorizing-using-bash-shell-colors/ | |
class Colors { | |
private static $foreground_colors = array( | |
'black'=>'0;30', | |
'dark_gray'=>'1;30', | |
'blue'=>'0;34', | |
'light_blue'=>'1;34', | |
'green'=>'0;32', | |
'light_green'=>'1;32', | |
'cyan'=>'0;36', | |
'light_cyan'=>'1;36', | |
'red'=>'0;31', | |
'light_red'=>'1;31', | |
'purple'=>'0;35', | |
'light_purple'=>'1;35', | |
'brown'=>'0;33', | |
'yellow'=>'1;33', | |
'light_gray'=>'0;37', | |
'white'=>'1;37' | |
); | |
private static $background_colors = array( | |
'black'=>'40', | |
'red'=>'41', | |
'green'=>'42', | |
'yellow'=>'43', | |
'cyan'=>'44', | |
'magenta'=>'45', | |
'light_cyan'=>'46', | |
'light_gray'=>'47' | |
); | |
// Returns colored string | |
public static function getColoredString($string, $foreground_color = null, $background_color = 'black') { | |
// Only colour the string if the user hasn't opted out of colour. | |
global $colour; | |
if (!$colour) return $string; | |
$colored_string = ""; | |
// Check if given foreground color found | |
if (isset(self::$foreground_colors[$foreground_color])) { | |
$colored_string .= "\033[" . self::$foreground_colors[$foreground_color] . "m"; | |
} | |
// Check if given background color found | |
if (isset(self::$background_colors[$background_color])) { | |
$colored_string .= "\033[" . self::$background_colors[$background_color] . "m"; | |
} | |
// Add string and end coloring | |
$colored_string .= $string . "\033[0m"; | |
return $colored_string; | |
} | |
// Returns all foreground color names | |
public static function getForegroundColors() { | |
return array_keys(self::$foreground_colors); | |
} | |
// Returns all background color names | |
public static function getBackgroundColors() { | |
return array_keys(self::$background_colors); | |
} | |
} | |
function getColoredString($string, $foreground_color = null, $background_color = 'black') { | |
return Colors::getColoredString($string,$foreground_color,$background_color); | |
} | |
function usage($filename) { | |
global $newline; | |
$usage = array( | |
'mastostats: get Mastodon network statistics from instances.mastodon.xyz, updates every 30 seconds', | |
'', | |
'Usage: '.$filename.' [more] [<topinstances>] [nocolour]', | |
'', | |
'more: Shows more statistics - ranks the top instances by statuses and connections as well as users', | |
'<topinstances>: Replace with a number to show the top <topinstances> number of instances. Defaults to 10.', | |
'nocolour: (or \'nocolor\'): Output will not be coloured.', | |
'' | |
); | |
echo implode($newline,$usage); | |
} | |
function comparison_by($property,$a,$b) { | |
if ((!property_exists($a,$property)) || (!property_exists($b,$property))) throw new Exception("Property does not exist in a passed object"); | |
if ($a->$property == 'unknown') $a->$property = 0; | |
if ($b->$property == 'unknown') $b->$property = 0; | |
if ($a->$property == $b->$property) return 0; | |
return ($a->$property > $b->$property ? -1 : 1); | |
} | |
function printinstancestats($instance_array,$title) { | |
global $newline,$morestats,$topinstances; | |
global $users,$statuses,$connections; | |
uasort($instance_array,function($a,$b) { | |
return comparison_by('users',$a,$b); | |
}); | |
echo getColoredString($newline.'Top ','white').getColoredString($topinstances.' ','light_green').$title.getColoredString(':','white').$newline; | |
if ($morestats) echo getColoredString('[By users]','light_cyan').$newline; | |
foreach (array_slice($instance_array,0,$topinstances) as $instance=>$instance_obj) { | |
echo getColoredString($instance,($instance_obj->up?'light_purple':'red')).getColoredString(': ','white'). | |
getColoredString($instance_obj->users.' users ','light_cyan'). | |
getColoredString('(','white').getColoredString((int)((int)($instance_obj->users)/$users*100).'%','light_green').getColoredString(') - ','white'). | |
getColoredString($instance_obj->statuses.' statuses ','light_red'). | |
getColoredString('(','white').getColoredString((int)((int)($instance_obj->statuses)/$statuses*100).'%','light_green').getColoredString(') - ','white'). | |
getColoredString($instance_obj->connections.' connections','cyan').$newline; | |
} | |
if ($morestats) { | |
uasort($instance_array,function($a,$b) { | |
return comparison_by('statuses',$a,$b); | |
}); | |
echo getColoredString('[By statuses]','light_red').$newline; | |
foreach (array_slice($instance_array,0,$topinstances) as $instance=>$instance_obj) { | |
echo getColoredString($instance,($instance_obj->up?'light_purple':'red')).getColoredString(': ','white'). | |
getColoredString($instance_obj->statuses.' statuses ','light_red'). | |
getColoredString('(','white').getColoredString((int)((int)($instance_obj->statuses)/$statuses*100).'%','light_green').getColoredString(') - ','white'). | |
getColoredString($instance_obj->users.' users ','light_cyan'). | |
getColoredString('(','white').getColoredString((int)((int)($instance_obj->users)/$users*100).'%','light_green').getColoredString(') - ','white'). | |
getColoredString($instance_obj->connections.' connections','cyan').$newline; | |
} | |
uasort($instance_array,function($a,$b) { | |
return comparison_by('connections',$a,$b); | |
}); | |
echo getColoredString('[By connections]','cyan').$newline; | |
foreach (array_slice($instance_array,0,$topinstances) as $instance=>$instance_obj) { | |
echo getColoredString($instance,($instance_obj->up?'light_purple':'red')).getColoredString(': ','white'). | |
getColoredString($instance_obj->connections.' connections','cyan').getColoredString(' - ','white'). | |
getColoredString($instance_obj->users.' users ','light_cyan'). | |
getColoredString('(','white').getColoredString((int)((int)($instance_obj->users)/$users*100).'%','light_green').getColoredString(') - ','white'). | |
getColoredString($instance_obj->statuses.' statuses ','light_red'). | |
getColoredString('(','white').getColoredString((int)((int)($instance_obj->statuses)/$statuses*100).'%','light_green').getColoredString(')','white').$newline; | |
} | |
} | |
} | |
$hit_once = false; | |
$old_users = 0; | |
$new_users = 0; | |
$new_users_since_start = 0; | |
$old_statuses = 0; | |
$new_statuses = 0; | |
$new_statuses_since_start = 0; | |
$newline = "\r\n"; | |
$unused_array = array(); | |
// It's a shame I have to do this, but... the following array will contain manually-added instances that are known to (now, or in the past) misrepresent their user count. | |
// Instances in this list will be hardcoded to show "unknown" (ie, 0) users. | |
$misbehaving_instances = array('mastodon.potproject.net'); | |
// arguments | |
$topinstances = 10; | |
$morestats = false; | |
$colour = true; | |
if ($argc > 1) { | |
$filename = array_shift($argv); | |
foreach ($argv as $arg) { | |
$arglower = str_replace('-','',strtolower($arg)); | |
if ($arglower == "more") { | |
$morestats = true; | |
continue; | |
} | |
if (($arglower == "nocolour") || ($arglower == "nocolor")) { // people will use the spelling that suits them, better to support both | |
$colour = false; | |
} | |
if (is_numeric($arg)) { | |
$topinstances = $arg; | |
} | |
if ($arglower == "help") die(usage($filename)); | |
} | |
} | |
while(1) { | |
$array = @json_decode(file_get_contents('https://instances.mastodon.xyz/instances.json')); | |
if (!$array) { | |
if (!$hit_once) { | |
echo getColoredString("Could not contact instances.mastodon.xyz, trying again in 30 seconds...",'red').$newline; | |
} | |
sleep(60); | |
continue; | |
} | |
// clear screen | |
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') { | |
proc_close(proc_open('cmd /c cls',array(STDIN,STDOUT,STDERR),$unused_array)); | |
} else { | |
echo chr(27).chr(91).'H'.chr(27).chr(91).'J'; | |
} | |
$count = count($array); | |
$open_instances = $all_instances = array(); | |
$users = 0; | |
$open_instance_count = 0; | |
$open_up_instance_count = 0; | |
$up_instance_count = 0; | |
$statuses = 0; | |
$connections = 0; | |
// iterate through all instances to get usercount, open instance list etc. | |
foreach($array as $instance) { | |
if ((in_array($instance->name,$misbehaving_instances)) || (!property_exists($instance,'users'))) $instance->users = 'unknown'; | |
if (!property_exists($instance,'statuses')) $instance->statuses = 'unknown'; | |
if (!property_exists($instance,'connections')) $instance->connections = 'unknown'; | |
$users += $instance->users; | |
$statuses += $instance->statuses; | |
$connections += $instance->connections; | |
if (@$instance->openRegistrations == true) { | |
$open_instance_count++; | |
$open_instances[(!$instance->up ? '[DOWN] ' : '').$instance->name] = (object)array('users'=>$instance->users,'statuses'=>$instance->statuses,'connections'=>$instance->connections,'up'=>$instance->up); | |
if (@$instance->up == true) $open_up_instance_count++; | |
} | |
$all_instances[(!$instance->up ? '[DOWN] ' : '').$instance->name] = (object)array('users'=>$instance->users,'statuses'=>$instance->statuses,'connections'=>$instance->connections,'up'=>$instance->up); | |
if (@$instance->up == true) $up_instance_count++; | |
} | |
echo getColoredString('For news and updates follow : ','white') . | |
getColoredString('@','light_green') . getColoredString('slipstream','yellow') . getColoredString('@','light_green') . getColoredString('mastodon.social','yellow') . $newline; | |
echo getColoredString('Instance count..............: ','white') . getColoredString($count,'yellow') . | |
getColoredString(' (','white') . getColoredString($up_instance_count,'light_green') . getColoredString(' up)','white') . $newline; | |
echo getColoredString('Open instances..............: ','white') . getColoredString($open_instance_count,'yellow') . | |
getColoredString(' (','white') . getColoredString($open_up_instance_count,'light_green') . getColoredString(' up)','white') . $newline; | |
echo getColoredString('Total users.................: ','white') . getColoredString($users,'yellow'); | |
if (($old_users != 0) && ($old_users != $users)) { | |
$new_users = $users - $old_users; | |
if ($new_users < 0) $new_users = 0; | |
$new_users_since_start += $new_users; | |
echo getColoredString(' (','white').getColoredString('+' . $new_users,'light_green') . getColoredString(')','white'); | |
} else if ($new_users > 0) { | |
echo getColoredString(' (','white').getColoredString('+' . $new_users,'light_green') . getColoredString(')','white'); | |
} | |
echo $newline; | |
echo getColoredString('New users...................: ','white') . | |
getColoredString($new_users_since_start,'green') . getColoredString(' since start of script','white') . $newline; | |
echo getColoredString('Average users/instance......: ','white') . getColoredString('~' . (int)($users/$count),'yellow') . $newline; | |
echo getColoredString('Total statuses..............: ','white') . getColoredString($statuses,'yellow'); | |
if (($old_statuses != 0) && ($old_statuses != $statuses)) { | |
$new_statuses = $statuses - $old_statuses; | |
if ($new_statuses < 0) $new_statuses = 0; | |
$new_statuses_since_start += $new_statuses; | |
echo getColoredString(' (','white') . getColoredString('+' . $new_statuses,'light_green') . getColoredString(')','white'); | |
} else if ($new_statuses > 0) { | |
echo getColoredString(' (','white') . getColoredString('+' . $new_statuses,'light_green') . getColoredString(')','white'); | |
} | |
echo $newline; | |
echo getColoredString('New statuses................: ','white') . getColoredString($new_statuses_since_start,'green') . getColoredString(' since start of script','white') . $newline; | |
echo getColoredString('Average statuses/instance...: ','white') . getColoredString('~' . (int)($statuses/$count),'yellow') . $newline; | |
echo getColoredString('Average connections/instance: ','white') . getColoredString('~' . (int)($connections/$count),'yellow') . $newline; | |
$old_users = $users; | |
$old_statuses = $statuses; | |
printinstancestats($open_instances,getColoredString('open instances','white')); | |
printinstancestats($all_instances,getColoredString('instances overall','white')); | |
$hit_once = true; | |
// wait 60 seconds for the next round | |
sleep(60); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment