mirror of
https://codeberg.org/fediverse/fediparty.git
synced 2024-11-25 01:51:28 +00:00
94 lines
3.3 KiB
Python
94 lines
3.3 KiB
Python
|
#!/usr/bin/env python3
|
||
|
|
||
|
import datetime
|
||
|
import json
|
||
|
import requests
|
||
|
|
||
|
SOFTWARES = ['diaspora', 'friendica', 'hubzilla', 'mastodon', 'gnusocial',
|
||
|
'pleroma', 'misskey', 'peertube', 'pixelfed', 'funkwhale',
|
||
|
'writefreely', 'plume', 'mobilizon', 'lemmy', 'gotosocial',
|
||
|
'owncast', 'bookwyrm', 'microblogpub', 'akkoma', 'calckey',
|
||
|
'hometown']
|
||
|
|
||
|
def number_to_string(number):
|
||
|
"""
|
||
|
Format number as string, using non-breaking space as a thousands separator.
|
||
|
"""
|
||
|
return f'{number:,}'.replace(',', '\u00a0')
|
||
|
|
||
|
class SoftwareNumbers:
|
||
|
"""
|
||
|
Contains numbers for a given software, or for Fediverse overall.
|
||
|
"""
|
||
|
def __init__(self, softwarename):
|
||
|
self.softwarename = softwarename
|
||
|
self.population = 0
|
||
|
self.active_users = 0
|
||
|
self.pods_num = 0
|
||
|
|
||
|
def __add__(self, other):
|
||
|
result = SoftwareNumbers(self.softwarename)
|
||
|
result.population = self.population + other.population
|
||
|
result.active_users = self.active_users + other.active_users
|
||
|
result.pods_num = self.pods_num + other.pods_num
|
||
|
return result
|
||
|
|
||
|
def as_object(self):
|
||
|
result = {}
|
||
|
result[self.softwarename] = {}
|
||
|
result[self.softwarename]['population'] = number_to_string(self.population)
|
||
|
result[self.softwarename]['activeUsers'] = number_to_string(self.active_users)
|
||
|
result[self.softwarename]['podsNum'] = number_to_string(self.pods_num)
|
||
|
return result
|
||
|
|
||
|
class StatsFetcher:
|
||
|
"""
|
||
|
Fetches Fediverse numbers and produces a report.
|
||
|
"""
|
||
|
def __init__(self):
|
||
|
self.session = requests.Session()
|
||
|
|
||
|
def __get_node_stats_for_software(self, softwarename):
|
||
|
query = '{ nodes(status: "UP", softwarename: "' \
|
||
|
+ softwarename \
|
||
|
+ '") { total_users, active_users_halfyear } }'
|
||
|
response = self.session.post('https://api.fediverse.observer/', data={'query': query})
|
||
|
return response.json().get('data', {}).get('nodes', [])
|
||
|
|
||
|
def __calculate_stats_for_software(self, softwarename):
|
||
|
node_stats = self.__get_node_stats_for_software(softwarename)
|
||
|
|
||
|
result = SoftwareNumbers(softwarename)
|
||
|
result.pods_num = len(node_stats)
|
||
|
for node in node_stats:
|
||
|
result.population += node.get('total_users', 0)
|
||
|
result.active_users += node.get('active_users_halfyear', 0)
|
||
|
|
||
|
return result
|
||
|
|
||
|
def get_numbers(self):
|
||
|
"""
|
||
|
Obtain an object with numbers for each of the supported Fediverse
|
||
|
platforms, and also a "fediverse" entry with totals.
|
||
|
"""
|
||
|
numbers = {}
|
||
|
numbers['lastUpdate'] = datetime.date.today().strftime('%d %b %Y')
|
||
|
|
||
|
fediverse = SoftwareNumbers('fediverse')
|
||
|
for i, software in enumerate(SOFTWARES):
|
||
|
print(f'({i+1:2}/{len(SOFTWARES):2}) Fetching stats for {software}...')
|
||
|
stats = self.__calculate_stats_for_software(software)
|
||
|
fediverse += stats
|
||
|
numbers |= stats.as_object()
|
||
|
|
||
|
numbers |= fediverse.as_object()
|
||
|
return { 'list': numbers }
|
||
|
|
||
|
if __name__ == '__main__':
|
||
|
fetcher = StatsFetcher()
|
||
|
numbers = fetcher.get_numbers()
|
||
|
FILEPATH = 'source/_data/numbers.json'
|
||
|
with open(FILEPATH, 'w') as f:
|
||
|
f.write(json.dumps(numbers, indent=2))
|
||
|
print(f'{FILEPATH} updated.')
|