#!/usr/bin/env ruby # SPDX-FileCopyrightText: 2022 Harald Eilertsen # SPDX-License-Identifier: AGPL-3.0-or-later # # A small program to query the-federation.info about the known Hubzilla # instances and output a simple overview of which versions are actively in use. # # Usage: # # ./hubzilla-versions.rb [] # # With no arguments it fetches the information directly from # the-federation.info. # # If you already have a downloaded json file with the proper fields available, # you can supply the file name as the only argument, and it will use that # instead of fetching it from the remote server. Mostly useful during # development/testing to not overload the remote server. # # Requirements: # # - A standard installation of the Ruby programming language. # (tested on Ruby version 3.0.3, but should afaict work on any # recent ruby.) # # License: # # This program is licensed under the GNU Affero General Public License version # 3.0 (or at your option a later version), which means you are free to use, # study, share and improve the program as you will. See # LICENSES/AGPL-3.0-or-later.txt for the details. # require 'erb' require 'json' require 'net/http' require 'time' require 'uri' query = <<~ENDQ { nodes( platform: "hubzilla" ) { host, version, updated, lastSuccess } } ENDQ graphql_uri = URI('https://the-federation.info/graphql') graphql_uri.query = "query=#{ERB::Util::url_encode(query)}"; if ARGV.empty? puts "Fetching results..." result = JSON.parse( Net::HTTP::get(graphql_uri, { 'Accept' => 'application/json' })) else puts "Reading #{ARGV[0]}..." result = JSON.parse(IO.read(ARGV[0])) end # Ignore any nodes we haven't seen in half a year cutoff = Time.now - (3600 * 24 * 30) nodes = result['data']['nodes'] .select { |node| Time::xmlschema(node['lastSuccess']) > cutoff } histogram = nodes.reduce(Hash.new) do |versions, node| v = node['version'] versions[v] = 0 unless versions.has_key?(v) versions[v] += 1 versions end total = histogram.values.sum sorted_keys = histogram.keys.sort do |a,b| v1 = a.split('.').map { |n| n.to_i } v2 = b.split('.').map { |n| n.to_i } v2 <=> v1 end sorted_keys.each do |k| puts "%-5s: %3d (%5.2f%%)" % [k, histogram[k], (histogram[k].to_f/total.to_f) * 100] end puts "----------" puts "total: %3d" % [total]