mirror of
https://codeberg.org/fediverse/fediparty.git
synced 2024-11-17 22:29:19 +00:00
Add script for updating source/_data/numbers.json
The JSON it produces is slightly different from what we had before: 1. indentation is a bit different; 2. it uses non-breaking space as thousands separator. I discussed this with @lostinlight and persuaded her that NBSP is less confusing than commas, because different cultures use different separators; 3. `lastUpdate` uses a format like "27 Jun 2023" rather than "27/06/23". Again, I discussed this with @lostinlight and she agreed that the new format is less confusing. Fixes #152.
This commit is contained in:
parent
75a45a99b7
commit
6c9725133c
|
@ -1,139 +1,115 @@
|
|||
|
||||
{
|
||||
"list":
|
||||
{
|
||||
"lastUpdate": "05/01/23",
|
||||
"diaspora":
|
||||
{
|
||||
"population": "638.079",
|
||||
"activeUsers": "33.328",
|
||||
"podsNum": "134"
|
||||
},
|
||||
"friendica":
|
||||
{
|
||||
"population": "20.923",
|
||||
"activeUsers": "6.990",
|
||||
"podsNum": "423"
|
||||
},
|
||||
"hubzilla":
|
||||
{
|
||||
"population": "4.917",
|
||||
"activeUsers": "2.197",
|
||||
"podsNum": "99"
|
||||
},
|
||||
"mastodon":
|
||||
{
|
||||
"population": "6.466.240",
|
||||
"activeUsers": "4.213.494",
|
||||
"podsNum": "12.573"
|
||||
},
|
||||
"gnusocial":
|
||||
{
|
||||
"population": "2.786",
|
||||
"activeUsers": "910",
|
||||
"podsNum": "24"
|
||||
},
|
||||
"pleroma":
|
||||
{
|
||||
"population": "125.595",
|
||||
"activeUsers": "53.669",
|
||||
"podsNum": "1.661"
|
||||
},
|
||||
"misskey":
|
||||
{
|
||||
"population": "37.056",
|
||||
"activeUsers": "19.771",
|
||||
"podsNum": "500"
|
||||
},
|
||||
"peertube":
|
||||
{
|
||||
"population": "309.723",
|
||||
"activeUsers": "90.525",
|
||||
"podsNum": "1.194"
|
||||
},
|
||||
"pixelfed":
|
||||
{
|
||||
"population": "124.005",
|
||||
"activeUsers": "53.107",
|
||||
"podsNum": "450"
|
||||
},
|
||||
"funkwhale":
|
||||
{
|
||||
"population": "5.253",
|
||||
"activeUsers": "2.112",
|
||||
"podsNum": "139"
|
||||
},
|
||||
"writefreely":
|
||||
{
|
||||
"population": "61.058",
|
||||
"activeUsers": "8.151",
|
||||
"podsNum": "567"
|
||||
},
|
||||
"plume":
|
||||
{
|
||||
"population": "23.557",
|
||||
"activeUsers": "",
|
||||
"podsNum": "63"
|
||||
},
|
||||
"mobilizon":
|
||||
{
|
||||
"population": "12.960",
|
||||
"activeUsers": "",
|
||||
"podsNum": "116"
|
||||
},
|
||||
"lemmy":
|
||||
{
|
||||
"population": "39.610",
|
||||
"activeUsers": "3.922",
|
||||
"podsNum": "87"
|
||||
},
|
||||
"gotosocial":
|
||||
{
|
||||
"population": "497",
|
||||
"activeUsers": "",
|
||||
"podsNum": "497"
|
||||
},
|
||||
"owncast":
|
||||
{
|
||||
"population": "158",
|
||||
"activeUsers": "158",
|
||||
"podsNum": "186"
|
||||
},
|
||||
"bookwyrm":
|
||||
{
|
||||
"population": "10.791",
|
||||
"activeUsers": "8.014",
|
||||
"podsNum": "65"
|
||||
},
|
||||
"microblogpub":
|
||||
{
|
||||
"population": "84",
|
||||
"activeUsers": "53",
|
||||
"podsNum": "100"
|
||||
},
|
||||
"akkoma":
|
||||
{
|
||||
"population": "9.425",
|
||||
"activeUsers": "1.076",
|
||||
"podsNum": "446"
|
||||
},
|
||||
"calckey":
|
||||
{
|
||||
"population": "2.700",
|
||||
"activeUsers": "2.265",
|
||||
"podsNum": "108"
|
||||
},
|
||||
"hometown":
|
||||
{
|
||||
"population": "10.304",
|
||||
"activeUsers": "8.537",
|
||||
"podsNum": "144"
|
||||
},
|
||||
"fediverse":
|
||||
{
|
||||
"population": "7.905.721",
|
||||
"activeUsers": "4.508.331",
|
||||
"podsNum": "19.576"
|
||||
}
|
||||
"list": {
|
||||
"lastUpdate": "27 Jun 2023",
|
||||
"diaspora": {
|
||||
"population": "640\u00a0909",
|
||||
"activeUsers": "22\u00a0827",
|
||||
"podsNum": "103"
|
||||
},
|
||||
"friendica": {
|
||||
"population": "20\u00a0553",
|
||||
"activeUsers": "5\u00a0285",
|
||||
"podsNum": "366"
|
||||
},
|
||||
"hubzilla": {
|
||||
"population": "5\u00a0163",
|
||||
"activeUsers": "2\u00a0138",
|
||||
"podsNum": "78"
|
||||
},
|
||||
"mastodon": {
|
||||
"population": "7\u00a0523\u00a0173",
|
||||
"activeUsers": "3\u00a0012\u00a0024",
|
||||
"podsNum": "11\u00a0580"
|
||||
},
|
||||
"gnusocial": {
|
||||
"population": "314",
|
||||
"activeUsers": "266",
|
||||
"podsNum": "21"
|
||||
},
|
||||
"pleroma": {
|
||||
"population": "104\u00a0287",
|
||||
"activeUsers": "34\u00a0135",
|
||||
"podsNum": "1\u00a0184"
|
||||
},
|
||||
"misskey": {
|
||||
"population": "288\u00a0957",
|
||||
"activeUsers": "27\u00a0181",
|
||||
"podsNum": "747"
|
||||
},
|
||||
"peertube": {
|
||||
"population": "280\u00a0741",
|
||||
"activeUsers": "61\u00a0665",
|
||||
"podsNum": "1\u00a0133"
|
||||
},
|
||||
"pixelfed": {
|
||||
"population": "154\u00a0117",
|
||||
"activeUsers": "50\u00a0221",
|
||||
"podsNum": "447"
|
||||
},
|
||||
"funkwhale": {
|
||||
"population": "8\u00a0547",
|
||||
"activeUsers": "1\u00a0697",
|
||||
"podsNum": "118"
|
||||
},
|
||||
"writefreely": {
|
||||
"population": "84\u00a0940",
|
||||
"activeUsers": "15\u00a0065",
|
||||
"podsNum": "548"
|
||||
},
|
||||
"plume": {
|
||||
"population": "23\u00a0810",
|
||||
"activeUsers": "1",
|
||||
"podsNum": "47"
|
||||
},
|
||||
"mobilizon": {
|
||||
"population": "17\u00a0141",
|
||||
"activeUsers": "17",
|
||||
"podsNum": "112"
|
||||
},
|
||||
"lemmy": {
|
||||
"population": "2\u00a0502\u00a0391",
|
||||
"activeUsers": "47\u00a0729",
|
||||
"podsNum": "980"
|
||||
},
|
||||
"gotosocial": {
|
||||
"population": "912",
|
||||
"activeUsers": "38",
|
||||
"podsNum": "595"
|
||||
},
|
||||
"owncast": {
|
||||
"population": "206",
|
||||
"activeUsers": "206",
|
||||
"podsNum": "206"
|
||||
},
|
||||
"bookwyrm": {
|
||||
"population": "15\u00a0126",
|
||||
"activeUsers": "8\u00a0161",
|
||||
"podsNum": "98"
|
||||
},
|
||||
"microblogpub": {
|
||||
"population": "80",
|
||||
"activeUsers": "63",
|
||||
"podsNum": "80"
|
||||
},
|
||||
"akkoma": {
|
||||
"population": "14\u00a0262",
|
||||
"activeUsers": "13\u00a0789",
|
||||
"podsNum": "498"
|
||||
},
|
||||
"calckey": {
|
||||
"population": "8\u00a0015",
|
||||
"activeUsers": "6\u00a0217",
|
||||
"podsNum": "339"
|
||||
},
|
||||
"hometown": {
|
||||
"population": "14\u00a0458",
|
||||
"activeUsers": "13\u00a0043",
|
||||
"podsNum": "160"
|
||||
},
|
||||
"fediverse": {
|
||||
"population": "11\u00a0708\u00a0102",
|
||||
"activeUsers": "3\u00a0321\u00a0768",
|
||||
"podsNum": "19\u00a0440"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
93
update-numbers.py
Executable file
93
update-numbers.py
Executable file
|
@ -0,0 +1,93 @@
|
|||
#!/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.')
|
Loading…
Reference in a new issue