2020-05-17 21:40:19 +02:00
import time
2020-05-17 21:28:03 +02:00
import urllib3
from datetime import datetime
from mastodon import Mastodon
import os
import json
import sys
import os . path
import requests
import psycopg2
from itertools import product
import multiprocessing
2020-06-03 19:20:32 +02:00
import aiohttp
import asyncio
import socket
2021-05-12 16:17:33 +02:00
import matplotlib . pyplot as plt
2021-08-31 11:11:24 +02:00
import pdb
2021-05-12 16:17:33 +02:00
plt . style . use ( ' seaborn ' )
start_time = time . time ( )
2021-05-14 13:14:31 +02:00
apis = [ ' /nodeinfo/2.0? ' , ' /nodeinfo/2.0.json? ' , ' /main/nodeinfo/2.0? ' , ' /api/statusnet/config? ' , ' /api/nodeinfo/2.0.json? ' , ' /api/nodeinfo? ' , ' /api/v1/instance? ' , ' /wp-json/nodeinfo/2.0? ' ]
2020-06-03 19:20:32 +02:00
client_exceptions = (
aiohttp . ClientResponseError ,
aiohttp . ClientConnectionError ,
aiohttp . ClientConnectorError ,
aiohttp . ClientError ,
asyncio . TimeoutError ,
socket . gaierror ,
)
2020-05-17 21:28:03 +02:00
def is_json ( myjson ) :
2021-05-14 13:14:31 +02:00
2020-06-03 19:20:32 +02:00
try :
json_object = json . loads ( myjson )
except ValueError as e :
2021-05-14 13:14:31 +02:00
print ( e )
2020-06-03 19:20:32 +02:00
return False
return True
2020-05-17 21:28:03 +02:00
2021-05-12 16:17:33 +02:00
def get_alive_servers ( server ) :
2021-05-14 13:14:31 +02:00
2021-05-12 16:17:33 +02:00
serv_api = ' '
serv_soft = ' '
soft_version = ' '
2020-05-17 21:28:03 +02:00
2020-06-03 19:20:32 +02:00
try :
2020-05-17 21:28:03 +02:00
2021-05-14 13:14:31 +02:00
conn = None
conn = psycopg2 . connect ( database = fediverse_db , user = fediverse_db_user , password = " " , host = " /var/run/postgresql " , port = " 5432 " )
2020-05-17 21:28:03 +02:00
2020-06-03 19:20:32 +02:00
cur = conn . cursor ( )
2020-05-17 21:28:03 +02:00
2021-08-23 17:23:42 +02:00
cur . execute ( " select alive, software, users_api, version, first_checked_at, downs from fediverse where server=( %s ) " , ( server , ) )
2020-05-17 21:28:03 +02:00
2020-06-03 19:20:32 +02:00
row = cur . fetchone ( )
2020-05-17 21:28:03 +02:00
2021-05-14 13:14:31 +02:00
if row is not None :
2020-05-19 23:33:55 +02:00
2020-06-03 19:20:32 +02:00
was_alive = row [ 0 ]
serv_soft = row [ 1 ]
serv_api = row [ 2 ]
2020-09-11 18:47:40 +02:00
soft_version = row [ 3 ]
2021-08-21 12:53:56 +02:00
first_checked_at = row [ 4 ]
2021-08-23 17:23:42 +02:00
downs_qty = row [ 5 ]
2020-06-03 19:20:32 +02:00
cur . close ( )
except ( Exception , psycopg2 . DatabaseError ) as error :
print ( error )
finally :
if conn is not None :
conn . close ( )
alive = False
2020-05-17 21:28:03 +02:00
try :
2021-08-21 12:53:56 +02:00
user_agent = { ' User-agent ' : ' Mozilla/5.0 ' }
data = requests . get ( ' https:// ' + server + serv_api , headers = user_agent , timeout = 3 )
2020-05-17 21:28:03 +02:00
2020-06-03 19:20:32 +02:00
if serv_soft == " mastodon " :
if serv_api == ' /nodeinfo/2.0? ' :
try :
users = data . json ( ) [ ' usage ' ] [ ' users ' ] [ ' total ' ]
2020-09-11 18:47:40 +02:00
soft_version = data . json ( ) [ ' software ' ] [ ' version ' ]
2020-06-04 19:38:53 +02:00
alive = True
2020-06-03 19:20:32 +02:00
except :
users = 0
2020-09-11 18:47:40 +02:00
soft_version = " "
2020-06-03 19:20:32 +02:00
if serv_api == ' /nodeinfo/2.0.json? ' :
try :
users = data . json ( ) [ ' usage ' ] [ ' users ' ] [ ' total ' ]
2020-09-11 18:47:40 +02:00
soft_version = data . json ( ) [ ' software ' ] [ ' version ' ]
2020-06-04 19:38:53 +02:00
alive = True
2020-06-03 19:20:32 +02:00
except :
users = 0
2020-09-11 18:47:40 +02:00
soft_version = " "
2020-06-03 19:20:32 +02:00
elif serv_api == ' /api/v1/instance? ' :
try :
users = data . json ( ) [ ' stats ' ] [ ' user_count ' ]
2020-09-11 18:47:40 +02:00
soft_version = data . json ( ) [ ' version ' ]
2020-06-04 19:38:53 +02:00
alive = True
2020-06-03 19:20:32 +02:00
except :
users = 0
2020-09-11 18:47:40 +02:00
soft_version = " "
2020-06-03 19:20:32 +02:00
if serv_soft == " pleroma " or serv_soft == " diaspora " or serv_soft == " peertube " or serv_soft == " pixelfed " or serv_soft == " hubzilla " or serv_soft == " writefreely " or serv_soft == " friendica " :
try :
users = data . json ( ) [ ' usage ' ] [ ' users ' ] [ ' total ' ]
2020-09-11 18:47:40 +02:00
soft_version = data . json ( ) [ ' software ' ] [ ' version ' ]
2020-06-04 19:38:53 +02:00
alive = True
2020-06-03 19:20:32 +02:00
except :
users = 0
2020-09-11 18:47:40 +02:00
soft_version = " "
2020-06-03 19:20:32 +02:00
if serv_soft == " gnusocialv2 " or serv_soft == " gnusocial " :
try :
users = data . json ( ) [ ' usage ' ] [ ' users ' ] [ ' total ' ]
if users == 0 :
users = data . json ( ) [ ' usage ' ] [ ' users ' ] [ ' activeHalfyear ' ]
2020-09-11 18:47:40 +02:00
soft_version = data . json ( ) [ ' software ' ] [ ' version ' ]
2020-06-04 19:38:53 +02:00
alive = True
2020-06-03 19:20:32 +02:00
except :
users = 0
2020-09-11 18:47:40 +02:00
soft_version = " "
2020-06-03 19:20:32 +02:00
if serv_soft == " plume " or serv_soft == ' red ' or serv_soft == " misskey " or serv_soft == " zap " or serv_soft == " prismo " or serv_soft == " ravenvale " or serv_soft == " osada " or serv_soft == " groundpolis " :
try :
users = data . json ( ) [ ' usage ' ] [ ' users ' ] [ ' total ' ]
2020-09-11 18:47:40 +02:00
soft_version = data . json ( ) [ ' software ' ] [ ' version ' ]
2020-06-04 19:38:53 +02:00
alive = True
2020-06-03 19:20:32 +02:00
except :
users = 0
2020-09-11 18:47:40 +02:00
soft_version = " "
2021-05-12 16:17:33 +02:00
if serv_soft == " ganggo " or serv_soft == " squs " or serv_soft == " dolphin " or serv_soft == " lemmy " or serv_soft == " wordpress " :
2020-06-03 19:20:32 +02:00
try :
users = data . json ( ) [ ' usage ' ] [ ' users ' ] [ ' total ' ]
2020-09-11 18:47:40 +02:00
soft_version = data . json ( ) [ ' software ' ] [ ' version ' ]
2021-05-12 16:17:33 +02:00
if serv_soft == " wordpress " and " activitypub " in data . json ( ) [ ' protocols ' ] :
alive = True
elif serv_soft == " wordpress " and " activitypub " not in data . json ( ) [ ' protocols ' ] :
alive = False
else :
alive = True
2020-06-03 19:20:32 +02:00
except :
2021-05-12 16:17:33 +02:00
2020-06-03 19:20:32 +02:00
users = 0
2020-09-11 18:47:40 +02:00
soft_version = " "
2020-05-17 21:28:03 +02:00
2021-05-12 16:17:33 +02:00
if alive :
2021-08-23 17:23:42 +02:00
if downs_qty != None :
downs = downs_qty
else :
downs = 0
2021-05-14 13:23:25 +02:00
if soft_version != " " and soft_version is not None :
2021-05-14 13:14:31 +02:00
print ( " Server " + str ( server ) + " ( " + serv_soft + " " + soft_version + " ) is alive! " )
2021-05-12 16:17:33 +02:00
else :
2021-05-14 13:14:31 +02:00
print ( " Server " + str ( server ) + " ( " + serv_soft + " ) is alive! " )
2020-05-17 21:28:03 +02:00
2021-08-23 17:23:42 +02:00
insert_sql = " INSERT INTO fediverse(server, users, updated_at, software, alive, users_api, version, first_checked_at, last_checked_at, downs) VALUES( %s , %s , %s , %s , %s , %s , %s , %s , %s , %s ) ON CONFLICT DO NOTHING "
2020-05-17 21:28:03 +02:00
2021-05-12 16:17:33 +02:00
conn = None
2020-05-17 21:28:03 +02:00
2021-05-12 16:17:33 +02:00
try :
2020-05-17 21:28:03 +02:00
2021-05-14 13:14:31 +02:00
conn = psycopg2 . connect ( database = fediverse_db , user = fediverse_db_user , password = " " , host = " /var/run/postgresql " , port = " 5432 " )
2020-05-17 21:28:03 +02:00
2021-05-12 16:17:33 +02:00
cur = conn . cursor ( )
2020-05-17 21:28:03 +02:00
2021-08-23 17:23:42 +02:00
cur . execute ( insert_sql , ( server , users , now , serv_soft , alive , serv_api , soft_version , now , now , downs ) )
2021-08-21 12:53:56 +02:00
if first_checked_at != None :
2021-08-23 17:23:42 +02:00
cur . execute ( " UPDATE fediverse SET users=( %s ), updated_at=( %s ), software=( %s ), alive=( %s ), users_api=( %s ), version=( %s ), last_checked_at=( %s ), downs=( %s ) where server=( %s ) " , ( users , now , serv_soft , alive , serv_api , soft_version , now , downs , server ) )
2021-08-21 12:53:56 +02:00
else :
2021-08-23 17:23:42 +02:00
cur . execute ( " UPDATE fediverse SET users=( %s ), updated_at=( %s ), software=( %s ), alive=( %s ), users_api=( %s ), version=( %s ), first_checked_at=( %s ), last_checked_at=( %s ), downs=( %s ) where server=( %s ) " , ( users , now , serv_soft , alive , serv_api , soft_version , now , now , downs , server ) )
2020-05-17 21:28:03 +02:00
2021-05-12 16:17:33 +02:00
cur . execute ( " UPDATE world SET checked= ' t ' where server=( %s ) " , ( server , ) )
2020-05-19 23:33:55 +02:00
2021-05-12 16:17:33 +02:00
conn . commit ( )
2020-05-17 21:28:03 +02:00
2021-05-12 16:17:33 +02:00
cur . close ( )
2020-05-17 21:28:03 +02:00
2021-05-12 16:17:33 +02:00
except ( Exception , psycopg2 . DatabaseError ) as error :
print ( error )
2020-05-17 21:28:03 +02:00
2021-05-12 16:17:33 +02:00
finally :
if conn is not None :
conn . close ( )
2020-05-17 21:28:03 +02:00
2020-06-03 19:20:32 +02:00
except urllib3 . exceptions . ProtocolError as protoerr :
2020-05-17 21:28:03 +02:00
2021-05-14 13:14:31 +02:00
print ( protoerr )
2020-06-03 19:20:32 +02:00
print ( " Server " + server + " is dead :-( " )
alive = False
pass
2020-05-17 21:28:03 +02:00
2020-06-03 19:20:32 +02:00
except requests . exceptions . ChunkedEncodingError as chunkerr :
2020-05-17 21:28:03 +02:00
2021-05-14 13:14:31 +02:00
print ( chunkerr )
2020-06-03 19:20:32 +02:00
print ( " Server " + server + " is dead :-( " )
alive = False
pass
2020-05-17 21:28:03 +02:00
2020-06-03 19:20:32 +02:00
except KeyError as e :
2020-05-17 21:28:03 +02:00
2021-05-14 13:14:31 +02:00
print ( e )
2020-06-03 19:20:32 +02:00
print ( " Server " + server + " is dead :-( " )
alive = False
pass
2020-05-17 21:28:03 +02:00
2020-06-03 19:20:32 +02:00
except ValueError as verr :
2020-05-17 21:28:03 +02:00
2021-05-14 13:14:31 +02:00
print ( verr )
2020-06-03 19:20:32 +02:00
print ( " Server " + server + " is dead :-( " )
alive = False
pass
2020-05-17 21:28:03 +02:00
2020-06-03 19:20:32 +02:00
except requests . exceptions . SSLError as errssl :
2020-05-17 21:28:03 +02:00
2021-05-14 13:14:31 +02:00
print ( errssl )
2020-06-03 19:20:32 +02:00
print ( " Server " + server + " is dead :-( " )
alive = False
pass
2020-05-17 21:28:03 +02:00
2020-06-03 19:20:32 +02:00
except requests . exceptions . HTTPError as errh :
2020-05-17 21:28:03 +02:00
2021-05-14 13:14:31 +02:00
print ( errh )
2020-06-03 19:20:32 +02:00
print ( " Server " + server + " is dead :-( " )
alive = False
pass
2020-05-17 21:28:03 +02:00
2020-06-03 19:20:32 +02:00
except requests . exceptions . ConnectionError as errc :
2020-05-17 21:28:03 +02:00
2021-05-14 13:14:31 +02:00
print ( errc )
2020-06-03 19:20:32 +02:00
print ( " Server " + server + " is dead :-( " )
alive = False
pass
2020-05-17 21:28:03 +02:00
2020-06-03 19:20:32 +02:00
except requests . exceptions . Timeout as errt :
2020-05-17 21:28:03 +02:00
2021-05-14 13:14:31 +02:00
print ( errt )
2020-06-03 19:20:32 +02:00
print ( " Server " + server + " is dead :-( " )
alive = False
pass
2020-05-17 21:28:03 +02:00
2020-06-03 19:20:32 +02:00
except requests . exceptions . RequestException as err :
2020-05-17 21:28:03 +02:00
2021-05-14 13:14:31 +02:00
print ( err )
2020-06-03 19:20:32 +02:00
print ( " Server " + server + " is dead :-( " )
alive = False
pass
2020-05-17 21:28:03 +02:00
2021-05-12 16:17:33 +02:00
except socket . gaierror as gai_error :
print ( gai_error )
pass
2021-05-14 13:14:31 +02:00
if alive is False :
2020-05-17 21:28:03 +02:00
2021-08-23 17:23:42 +02:00
if downs_qty != None :
downs = downs_qty + 1
else :
downs = 1
2020-06-03 19:20:32 +02:00
conn = None
2020-05-17 21:28:03 +02:00
2020-06-03 19:20:32 +02:00
try :
2020-05-17 21:28:03 +02:00
2020-06-03 19:20:32 +02:00
conn = psycopg2 . connect ( database = fediverse_db , user = fediverse_db_user , password = " " ,
host = " /var/run/postgresql " , port = " 5432 " )
2020-05-17 21:28:03 +02:00
2020-06-03 19:20:32 +02:00
cur = conn . cursor ( )
2021-08-21 12:53:56 +02:00
if first_checked_at != None :
2021-08-23 17:23:42 +02:00
cur . execute ( " UPDATE fediverse SET updated_at=( %s ), alive=( %s ), first_checked_at=( %s ), downs=( %s ) where server=( %s ) " , ( now , alive , NULL , downs , server ) )
2021-08-21 12:53:56 +02:00
else :
2021-08-23 17:23:42 +02:00
cur . execute ( " UPDATE fediverse SET updated_at=( %s ), alive=( %s ), downs=( %s ) where server=( %s ) " , ( now , alive , downs , server ) )
2020-06-03 19:20:32 +02:00
cur . execute ( " UPDATE world SET checked= ' t ' where server=( %s ) " , ( server , ) )
conn . commit ( )
2020-05-17 21:28:03 +02:00
2020-06-03 19:20:32 +02:00
cur . close ( )
2020-05-17 21:28:03 +02:00
2020-06-03 19:20:32 +02:00
except ( Exception , psycopg2 . DatabaseError ) as error :
print ( error )
2020-05-17 21:28:03 +02:00
2020-06-03 19:20:32 +02:00
finally :
2020-05-17 21:28:03 +02:00
2020-06-03 19:20:32 +02:00
if conn is not None :
conn . close ( )
2020-05-17 21:28:03 +02:00
2020-09-11 18:47:40 +02:00
def write_api ( server , software , users , alive , api , soft_version ) :
2020-05-17 21:28:03 +02:00
2020-09-11 18:47:40 +02:00
insert_sql = " INSERT INTO fediverse(server, updated_at, software, users, alive, users_api, version) VALUES( %s , %s , %s , %s , %s , %s , %s ) ON CONFLICT DO NOTHING "
2020-06-03 19:20:32 +02:00
conn = None
try :
2021-05-14 13:14:31 +02:00
conn = psycopg2 . connect ( database = fediverse_db , user = fediverse_db_user , password = " " , host = " /var/run/postgresql " , port = " 5432 " )
2020-06-03 19:20:32 +02:00
cur = conn . cursor ( )
2020-09-11 18:47:40 +02:00
cur . execute ( insert_sql , ( server , now , software , users , alive , api , soft_version ) )
2020-06-03 19:20:32 +02:00
2020-09-11 18:47:40 +02:00
cur . execute ( " UPDATE fediverse SET updated_at=( %s ), software=( %s ), users=( %s ), alive=( %s ), users_api=( %s ), version=( %s ) where server=( %s ) " , ( now , software , users , alive , api , soft_version , server ) )
2020-06-03 19:20:32 +02:00
cur . execute ( " UPDATE world SET checked= ' t ' where server=( %s ) " , ( server , ) )
2020-05-17 21:28:03 +02:00
2020-06-03 19:20:32 +02:00
conn . commit ( )
2020-05-17 21:28:03 +02:00
2020-06-03 19:20:32 +02:00
cur . close ( )
2020-05-17 21:28:03 +02:00
2020-06-03 19:20:32 +02:00
except ( Exception , psycopg2 . DatabaseError ) as error :
2020-06-04 19:38:53 +02:00
2020-06-03 19:20:32 +02:00
print ( error )
2020-05-17 21:28:03 +02:00
2020-06-03 19:20:32 +02:00
finally :
2020-05-17 21:28:03 +02:00
2020-06-03 19:20:32 +02:00
if conn is not None :
2020-06-04 19:38:53 +02:00
2020-05-17 21:28:03 +02:00
conn . close ( )
2020-06-03 19:20:32 +02:00
async def getsoft ( server ) :
2020-05-17 21:28:03 +02:00
2020-06-03 19:20:32 +02:00
try :
2020-05-17 21:28:03 +02:00
2020-06-03 19:20:32 +02:00
socket . gethostbyname ( server )
2020-05-17 21:28:03 +02:00
2020-06-03 19:20:32 +02:00
except socket . gaierror :
2020-05-17 21:28:03 +02:00
2021-05-12 16:17:33 +02:00
pass
2020-06-03 19:20:32 +02:00
return
2020-05-17 21:28:03 +02:00
2020-06-03 19:20:32 +02:00
soft = ' '
url = ' https:// ' + server
timeout = aiohttp . ClientTimeout ( total = 3 )
async with aiohttp . ClientSession ( timeout = timeout ) as session :
for api in apis :
try :
async with session . get ( url + api ) as response :
if response . status == 200 :
try :
response_json = await response . json ( )
except :
pass
except aiohttp . ClientConnectorError as err :
2021-05-14 13:14:31 +02:00
print ( err )
2020-06-03 19:20:32 +02:00
pass
else :
2021-05-14 13:14:31 +02:00
if response . status == 200 and api != ' /api/v1/instance? ' :
try :
soft = response_json [ ' software ' ] [ ' name ' ]
soft = soft . lower ( )
soft_version = response_json [ ' software ' ] [ ' version ' ]
users = response_json [ ' usage ' ] [ ' users ' ] [ ' total ' ]
if users > 1000000 :
return
alive = True
write_api ( server , soft , users , alive , api , soft_version )
print ( " Server " + server + " ( " + soft + " " + soft_version + " ) is alive! " )
return
except :
pass
if response . status == 200 and soft == ' ' and api == " /api/v1/instance? " :
soft = ' mastodon '
users = response_json [ ' stats ' ] [ ' user_count ' ]
soft_version = response_json [ ' version ' ]
if users > 1000000 :
return
alive = True
write_api ( server , soft , users , alive , api )
print ( " Server " + server + " ( " + soft + " ) is alive! " )
2020-05-17 21:28:03 +02:00
2020-06-03 19:20:32 +02:00
def getserver ( server , x ) :
2020-05-17 21:28:03 +02:00
2020-06-03 19:20:32 +02:00
server = server [ 0 ] . rstrip ( ' . ' ) . lower ( )
2020-05-17 21:28:03 +02:00
2020-06-03 19:20:32 +02:00
if server . find ( " . " ) == - 1 :
return
if server . find ( " @ " ) != - 1 :
2021-05-14 13:14:31 +02:00
return
2020-06-03 19:20:32 +02:00
if server . find ( " / " ) != - 1 :
2021-05-14 13:14:31 +02:00
return
2020-06-03 19:20:32 +02:00
if server . find ( " : " ) != - 1 :
2021-05-14 13:14:31 +02:00
return
2020-05-17 21:28:03 +02:00
2020-06-03 19:20:32 +02:00
try :
2020-05-17 21:28:03 +02:00
2020-06-03 19:20:32 +02:00
loop = asyncio . get_event_loop ( )
coroutines = [ getsoft ( server ) ]
soft = loop . run_until_complete ( asyncio . gather ( * coroutines , return_exceptions = True ) )
except :
2020-05-17 21:28:03 +02:00
pass
2021-05-12 16:17:33 +02:00
def set_world_servers_check_to_false ( ) :
2020-05-17 21:28:03 +02:00
2020-06-03 19:20:32 +02:00
############################################################################
# set all world servers's checked column to False
2020-05-17 21:28:03 +02:00
2020-06-03 19:20:32 +02:00
try :
conn = None
2021-05-14 13:14:31 +02:00
conn = psycopg2 . connect ( database = fediverse_db , user = fediverse_db_user , password = " " , host = " /var/run/postgresql " , port = " 5432 " )
2020-06-03 19:20:32 +02:00
cur = conn . cursor ( )
cur . execute ( " UPDATE world SET checked= ' f ' " )
conn . commit ( )
2020-05-17 21:28:03 +02:00
2020-06-03 19:20:32 +02:00
cur . close ( )
2020-05-17 21:28:03 +02:00
2020-06-03 19:20:32 +02:00
except ( Exception , psycopg2 . DatabaseError ) as error :
2020-05-17 21:28:03 +02:00
2020-06-03 19:20:32 +02:00
print ( error )
finally :
if conn is not None :
conn . close ( )
2021-05-12 16:17:33 +02:00
def get_last_checked_servers ( ) :
2020-06-03 19:20:32 +02:00
2021-05-12 16:17:33 +02:00
############################################################################
# get last checked servers from fediverse DB
2020-06-03 19:20:32 +02:00
alive_servers = [ ]
try :
conn = None
2021-05-14 13:14:31 +02:00
conn = psycopg2 . connect ( database = fediverse_db , user = fediverse_db_user , password = " " , host = " /var/run/postgresql " , port = " 5432 " )
2020-06-03 19:20:32 +02:00
cur = conn . cursor ( )
2021-05-14 13:14:31 +02:00
# get world servers list
2020-06-03 19:20:32 +02:00
cur . execute ( " select server from world where server in (select server from fediverse where users_api != ' ' ) " )
alive_servers = [ ]
for row in cur :
alive_servers . append ( row [ 0 ] )
cur . close ( )
except ( Exception , psycopg2 . DatabaseError ) as error :
print ( error )
finally :
if conn is not None :
conn . close ( )
2021-05-12 16:17:33 +02:00
return alive_servers
2020-06-03 19:20:32 +02:00
2021-05-12 16:17:33 +02:00
def mastodon ( ) :
2020-06-03 19:20:32 +02:00
2021-05-12 16:17:33 +02:00
# Load secrets from secrets file
secrets_filepath = " secrets/secrets.txt "
2021-05-14 13:14:31 +02:00
uc_client_id = get_parameter ( " uc_client_id " , secrets_filepath )
2021-05-12 16:17:33 +02:00
uc_client_secret = get_parameter ( " uc_client_secret " , secrets_filepath )
2021-05-14 13:14:31 +02:00
uc_access_token = get_parameter ( " uc_access_token " , secrets_filepath )
2020-06-03 19:20:32 +02:00
2021-05-12 16:17:33 +02:00
# Load configuration from config file
config_filepath = " config/config.txt "
mastodon_hostname = get_parameter ( " mastodon_hostname " , config_filepath )
2020-06-03 19:20:32 +02:00
2021-05-12 16:17:33 +02:00
# Initialise Mastodon API
mastodon = Mastodon (
2021-05-14 13:14:31 +02:00
client_id = uc_client_id ,
client_secret = uc_client_secret ,
access_token = uc_access_token ,
api_base_url = ' https:// ' + mastodon_hostname ,
2021-05-12 16:17:33 +02:00
)
2020-06-03 19:20:32 +02:00
2021-05-12 16:17:33 +02:00
# Initialise access headers
2021-05-14 13:14:31 +02:00
headers = { ' Authorization ' : ' Bearer %s ' % uc_access_token }
2020-05-17 21:28:03 +02:00
2021-05-12 16:17:33 +02:00
return ( mastodon , mastodon_hostname )
2020-05-17 21:28:03 +02:00
2021-05-12 16:17:33 +02:00
def db_config ( ) :
2020-05-17 21:28:03 +02:00
2021-05-12 16:17:33 +02:00
# Load db configuration from config file
config_filepath = " config/db_config.txt "
fediverse_db = get_parameter ( " fediverse_db " , config_filepath )
fediverse_db_user = get_parameter ( " fediverse_db_user " , config_filepath )
2020-05-17 21:28:03 +02:00
2021-05-12 16:17:33 +02:00
return ( fediverse_db , fediverse_db_user )
2020-05-17 21:28:03 +02:00
2021-05-12 16:17:33 +02:00
def usage ( ) :
2020-05-17 21:28:03 +02:00
2021-05-12 16:17:33 +02:00
print ( ' usage: python ' + sys . argv [ 0 ] + ' --multi ' + ' (multiprocessing, fast) ' )
print ( ' usage: python ' + sys . argv [ 0 ] + ' --mono ' + ' (one process, slow) ' )
2020-05-17 21:28:03 +02:00
2021-05-12 16:17:33 +02:00
# Returns the parameter from the specified file
2021-05-14 13:14:31 +02:00
def get_parameter ( parameter , file_path ) :
2021-05-12 16:17:33 +02:00
# Check if secrets file exists
if not os . path . isfile ( file_path ) :
print ( " File %s not found, exiting. " % file_path )
sys . exit ( 0 )
2020-05-17 21:28:03 +02:00
2021-05-12 16:17:33 +02:00
# Find parameter in file
2021-05-14 13:14:31 +02:00
with open ( file_path ) as f :
2021-05-12 16:17:33 +02:00
for line in f :
2021-05-14 13:14:31 +02:00
if line . startswith ( parameter ) :
2021-05-12 16:17:33 +02:00
return line . replace ( parameter + " : " , " " ) . strip ( )
2020-05-17 21:28:03 +02:00
2021-05-12 16:17:33 +02:00
# Cannot find parameter, exit
print ( file_path + " Missing parameter %s " % parameter )
sys . exit ( 0 )
2020-05-17 21:28:03 +02:00
2021-05-12 16:17:33 +02:00
###############################################################################
# main
2020-08-11 20:07:10 +02:00
2021-05-12 16:17:33 +02:00
if __name__ == ' __main__ ' :
2020-05-19 23:33:55 +02:00
2021-05-12 16:17:33 +02:00
# usage modes
2020-05-19 23:33:55 +02:00
2021-05-12 16:17:33 +02:00
if len ( sys . argv ) == 1 :
2020-05-19 23:33:55 +02:00
2021-05-12 16:17:33 +02:00
usage ( )
2020-05-19 23:33:55 +02:00
2021-05-12 16:17:33 +02:00
elif len ( sys . argv ) == 2 :
2020-05-19 23:33:55 +02:00
2021-05-12 16:17:33 +02:00
if sys . argv [ 1 ] == ' --multi ' :
now = datetime . now ( )
2020-05-19 23:33:55 +02:00
2021-05-12 16:17:33 +02:00
mastodon , mastodon_hostname = mastodon ( )
2020-05-19 23:33:55 +02:00
2021-05-12 16:17:33 +02:00
fediverse_db , fediverse_db_user = db_config ( )
2020-05-19 23:33:55 +02:00
2021-05-12 16:17:33 +02:00
total_servers = 0
total_users = 0
2020-05-19 23:33:55 +02:00
2021-05-12 16:17:33 +02:00
set_world_servers_check_to_false ( )
2020-05-19 23:33:55 +02:00
2021-05-12 16:17:33 +02:00
alive_servers = get_last_checked_servers ( )
###########################################################################
# multiprocessing!
nprocs = multiprocessing . cpu_count ( )
with multiprocessing . Pool ( processes = 64 ) as pool :
results = pool . starmap ( get_alive_servers , product ( alive_servers ) )
elif sys . argv [ 1 ] == ' --mono ' :
now = datetime . now ( )
mastodon , mastodon_hostname = mastodon ( )
fediverse_db , fediverse_db_user = db_config ( )
total_servers = 0
total_users = 0
set_world_servers_check_to_false ( )
alive_servers = get_last_checked_servers ( )
i = 0
while i < len ( alive_servers ) :
get_alive_servers ( alive_servers [ i ] )
i + = 1
else :
usage ( )
###########################################################################
# get current total servers and users, get users from every software
gettotals_sql = " select count(server), sum(users) from fediverse where alive "
get_soft_totals_sql = " select software, sum(users) as users, count(server) as servers from fediverse where users != 0 and alive group by software order by users desc "
soft_total_project = [ ]
soft_total_users = [ ]
soft_total_servers = [ ]
try :
conn = None
2021-05-14 13:14:31 +02:00
conn = psycopg2 . connect ( database = fediverse_db , user = fediverse_db_user , password = " " , host = " /var/run/postgresql " , port = " 5432 " )
2021-05-12 16:17:33 +02:00
cur = conn . cursor ( )
cur . execute ( gettotals_sql )
row = cur . fetchone ( )
total_servers = row [ 0 ]
total_users = row [ 1 ]
cur . execute ( get_soft_totals_sql )
rows = cur . fetchall ( )
for row in rows :
soft_total_project . append ( row [ 0 ] )
soft_total_users . append ( row [ 1 ] )
soft_total_servers . append ( row [ 2 ] )
cur . close ( )
except ( Exception , psycopg2 . DatabaseError ) as error :
print ( error )
finally :
if conn is not None :
conn . close ( )
###########################################################################
# get last check values and write current total ones
select_sql = " select total_servers, total_users from totals order by datetime desc limit 1 "
insert_sql = " INSERT INTO totals(datetime, total_servers, total_users) VALUES( %s , %s , %s ) "
try :
conn = None
2021-05-14 13:14:31 +02:00
conn = psycopg2 . connect ( database = fediverse_db , user = fediverse_db_user , password = " " , host = " /var/run/postgresql " , port = " 5432 " )
2021-05-12 16:17:33 +02:00
cur = conn . cursor ( )
cur . execute ( select_sql )
row = cur . fetchone ( )
2021-05-14 13:14:31 +02:00
if row is not None :
2021-05-12 16:17:33 +02:00
servers_before = row [ 0 ]
users_before = row [ 1 ]
else :
servers_before = 0
users_before = 0
cur . execute ( insert_sql , ( now , total_servers , total_users ) )
conn . commit ( )
cur . close ( )
evo_servers = total_servers - servers_before
evo_users = total_users - users_before
except ( Exception , psycopg2 . DatabaseError ) as error :
print ( error )
finally :
if conn is not None :
conn . close ( )
################################################################################
# write evo values
insert_sql = " INSERT INTO evo(datetime, servers, users) VALUES( %s , %s , %s ) "
2020-05-19 23:33:55 +02:00
2020-06-03 19:20:32 +02:00
conn = None
2020-05-19 23:33:55 +02:00
2021-05-12 16:17:33 +02:00
try :
2020-05-19 23:33:55 +02:00
2021-05-14 13:14:31 +02:00
conn = psycopg2 . connect ( database = fediverse_db , user = fediverse_db_user , password = " " , host = " /var/run/postgresql " , port = " 5432 " )
2020-05-19 23:33:55 +02:00
2021-05-12 16:17:33 +02:00
cur = conn . cursor ( )
2020-05-19 23:33:55 +02:00
2021-05-12 16:17:33 +02:00
cur . execute ( insert_sql , ( now , evo_servers , evo_users ) )
2020-05-17 21:28:03 +02:00
2021-05-12 16:17:33 +02:00
conn . commit ( )
2020-05-17 21:28:03 +02:00
2021-05-12 16:17:33 +02:00
cur . close ( )
2020-05-17 21:28:03 +02:00
2021-05-12 16:17:33 +02:00
except ( Exception , psycopg2 . DatabaseError ) as error :
2020-05-17 21:28:03 +02:00
2021-05-12 16:17:33 +02:00
print ( error )
2020-05-17 21:28:03 +02:00
2021-05-12 16:17:33 +02:00
finally :
2020-05-17 21:28:03 +02:00
2021-05-12 16:17:33 +02:00
if conn is not None :
2020-05-17 21:28:03 +02:00
2021-05-12 16:17:33 +02:00
conn . close ( )
2020-05-17 21:28:03 +02:00
2021-05-12 16:17:33 +02:00
##############################################################################
# get world's last update datetime
2020-05-17 21:28:03 +02:00
2021-05-12 16:17:33 +02:00
conn = None
try :
2021-05-14 13:14:31 +02:00
conn = psycopg2 . connect ( database = fediverse_db , user = fediverse_db_user , password = " " , host = " /var/run/postgresql " , port = " 5432 " )
2021-05-12 16:17:33 +02:00
cur = conn . cursor ( )
cur . execute ( " select updated_at from world order by updated_at desc limit 1 " )
row = cur . fetchone ( )
last_update = row [ 0 ]
last_update = last_update . strftime ( ' % m/ %d / % Y, % H: % M: % S ' )
cur . close ( )
except ( Exception , psycopg2 . DatabaseError ) as error :
print ( error )
finally :
if conn is not None :
conn . close ( )
##############################################################################
# get max servers and users
2020-05-17 21:28:03 +02:00
2020-06-03 19:20:32 +02:00
conn = None
2020-05-17 21:28:03 +02:00
2021-05-12 16:17:33 +02:00
try :
2020-05-17 21:28:03 +02:00
2021-05-14 13:14:31 +02:00
conn = psycopg2 . connect ( database = fediverse_db , user = fediverse_db_user , password = " " , host = " /var/run/postgresql " , port = " 5432 " )
2020-05-17 21:28:03 +02:00
2021-05-12 16:17:33 +02:00
cur = conn . cursor ( )
2020-05-17 21:28:03 +02:00
2021-05-12 16:17:33 +02:00
cur . execute ( " select MAX(total_servers) from totals " )
2020-05-17 21:28:03 +02:00
2021-05-12 16:17:33 +02:00
row = cur . fetchone ( )
2020-05-17 21:28:03 +02:00
2021-05-14 13:14:31 +02:00
if row is not None :
2020-05-17 21:28:03 +02:00
2021-05-12 16:17:33 +02:00
max_servers = row [ 0 ]
2020-05-17 21:28:03 +02:00
2021-05-12 16:17:33 +02:00
else :
2020-05-17 21:28:03 +02:00
2021-05-12 16:17:33 +02:00
max_servers = 0
2020-05-17 21:28:03 +02:00
2021-05-12 16:17:33 +02:00
cur . execute ( " select MAX(total_users) from totals " )
2020-05-17 21:28:03 +02:00
2021-05-12 16:17:33 +02:00
row = cur . fetchone ( )
2020-05-17 21:28:03 +02:00
2021-05-14 13:14:31 +02:00
if row is not None :
2020-05-17 21:28:03 +02:00
2021-05-12 16:17:33 +02:00
max_users = row [ 0 ]
else :
max_users = 0
cur . close ( )
except ( Exception , psycopg2 . DatabaseError ) as error :
print ( error )
finally :
if conn is not None :
conn . close ( )
###############################################################################
# get plots
servers_plots = [ ]
users_plots = [ ]
2020-05-17 21:28:03 +02:00
2020-06-03 19:20:32 +02:00
conn = None
2020-05-17 21:28:03 +02:00
2021-05-12 16:17:33 +02:00
try :
2020-05-17 21:28:03 +02:00
2021-05-14 13:14:31 +02:00
conn = psycopg2 . connect ( database = fediverse_db , user = fediverse_db_user , password = " " , host = " /var/run/postgresql " , port = " 5432 " )
2020-05-17 21:28:03 +02:00
2021-05-12 16:17:33 +02:00
cur = conn . cursor ( )
2020-05-17 21:28:03 +02:00
2021-05-12 16:17:33 +02:00
cur . execute ( " select total_servers, total_users from totals order by datetime desc limit 14 " )
2020-05-17 21:28:03 +02:00
2021-05-12 16:17:33 +02:00
rows = cur . fetchall ( )
2020-05-17 21:28:03 +02:00
2021-05-12 16:17:33 +02:00
for row in rows :
2020-06-03 19:20:32 +02:00
2021-05-12 16:17:33 +02:00
servers_plots . append ( row [ 0 ] )
2020-06-03 19:20:32 +02:00
2021-05-12 16:17:33 +02:00
users_plots . append ( row [ 1 ] )
2020-06-03 19:20:32 +02:00
2021-05-12 16:17:33 +02:00
cur . close ( )
2020-05-17 21:28:03 +02:00
2021-05-12 16:17:33 +02:00
except ( Exception , psycopg2 . DatabaseError ) as error :
2020-05-17 21:28:03 +02:00
2021-05-12 16:17:33 +02:00
print ( error )
2020-05-17 21:28:03 +02:00
2021-05-12 16:17:33 +02:00
finally :
2020-05-17 21:28:03 +02:00
2021-05-12 16:17:33 +02:00
if conn is not None :
2020-05-17 21:28:03 +02:00
2021-05-12 16:17:33 +02:00
conn . close ( )
2020-06-03 19:20:32 +02:00
2021-05-12 16:17:33 +02:00
###############################################################################
# generate graphs
2020-06-03 19:20:32 +02:00
2021-05-14 13:14:31 +02:00
plt . plot ( [ - 6 , - 5 , - 4 , - 3 , - 2 , - 1 , 0 ] , [ servers_plots [ 6 ] , servers_plots [ 5 ] , servers_plots [ 4 ] , servers_plots [ 3 ] , servers_plots [ 2 ] , servers_plots [ 1 ] , servers_plots [ 0 ] ] , marker = ' o ' , color = ' mediumseagreen ' )
2020-05-17 21:28:03 +02:00
2021-05-12 16:17:33 +02:00
plt . plot ( [ - 6 , - 5 , - 4 , - 3 , - 2 , - 1 , 0 ] , [ max_servers , max_servers , max_servers , max_servers , max_servers , max_servers , max_servers ] , color = ' red ' )
2020-05-17 21:28:03 +02:00
2021-05-14 13:14:31 +02:00
plt . title ( ' fediverse: total alive servers (max: ' + str ( f " { max_servers : , } " + ' ) ' ) , loc = ' right ' , color = ' blue ' )
2020-05-17 21:28:03 +02:00
2021-05-12 16:17:33 +02:00
plt . xlabel ( ' Last seven days ' )
2020-05-17 21:28:03 +02:00
2021-05-12 16:17:33 +02:00
plt . ylabel ( ' fediverse alive servers ' )
2020-05-17 21:28:03 +02:00
2021-05-12 16:17:33 +02:00
plt . legend ( ( ' servers ' , ' max ' ) , shadow = True , loc = ( 0.01 , 1.00 ) , handlelength = 1.5 , fontsize = 10 )
2020-05-17 21:28:03 +02:00
2021-05-12 16:17:33 +02:00
plt . savefig ( ' servers.png ' )
2020-05-17 21:28:03 +02:00
2021-05-12 16:17:33 +02:00
plt . close ( )
2020-05-17 21:28:03 +02:00
2021-05-12 16:17:33 +02:00
plt . plot ( [ - 6 , - 5 , - 4 , - 3 , - 2 , - 1 , 0 ] , [ users_plots [ 6 ] , users_plots [ 5 ] , users_plots [ 4 ] , users_plots [ 3 ] , users_plots [ 2 ] , users_plots [ 1 ] , users_plots [ 0 ] ] , marker = ' o ' , color = ' royalblue ' )
2020-05-17 21:28:03 +02:00
2021-05-12 16:17:33 +02:00
plt . plot ( [ - 6 , - 5 , - 4 , - 3 , - 2 , - 1 , 0 ] , [ max_users , max_users , max_users , max_users , max_users , max_users , max_users ] , color = ' red ' )
2020-05-17 21:28:03 +02:00
2021-05-14 13:14:31 +02:00
plt . title ( ' fediverse: total registered users (max: ' + str ( f " { max_users : , } " + ' ) ' ) , loc = ' right ' , color = ' royalblue ' )
2020-05-17 21:28:03 +02:00
2021-05-12 16:17:33 +02:00
plt . legend ( ( ' users ' , ' max ' ) , shadow = True , loc = ( 0.01 , 0.80 ) , handlelength = 1.5 , fontsize = 10 )
2020-05-17 21:28:03 +02:00
2021-05-12 16:17:33 +02:00
plt . xlabel ( ' Last seven days ' )
2020-05-17 21:28:03 +02:00
2021-05-12 16:17:33 +02:00
plt . ylabel ( ' Registered users ' )
2020-05-17 21:28:03 +02:00
2021-05-12 16:17:33 +02:00
plt . savefig ( ' users.png ' )
2020-05-17 21:28:03 +02:00
2021-05-12 16:17:33 +02:00
plt . close ( )
2020-05-19 23:33:55 +02:00
2021-05-12 16:17:33 +02:00
###############################################################################
# T O O T !
2020-05-19 23:33:55 +02:00
2021-05-12 16:17:33 +02:00
toot_text = " #fediverse alive servers stats " + " \n "
toot_text + = " \n "
if evo_servers > = 0 :
toot_text + = " alive servers: " + str ( f " { total_servers : , } " ) + " (+ " + str ( f " { evo_servers : , } " ) + " ) \n "
toot_text + = " max: " + str ( f " { max_servers : , } " ) + " \n "
elif evo_servers < 0 :
toot_text + = " alive servers: " + str ( f " { total_servers : , } " ) + " ( " + str ( f " { evo_servers : , } " ) + " ) \n "
toot_text + = " max: " + str ( f " { max_servers : , } " ) + " \n "
if evo_users > = 0 :
toot_text + = " total users: " + str ( f " { total_users : , } " ) + " (+ " + str ( f " { evo_users : , } " ) + " ) \n "
toot_text + = " max: " + str ( f " { max_users : , } " ) + " \n "
elif evo_users < 0 :
toot_text + = " total users: " + str ( f " { total_users : , } " ) + " ( " + str ( f " { evo_users : , } " ) + " ) \n "
toot_text + = " max: " + str ( f " { max_users : , } " ) + " \n "
2020-05-19 23:33:55 +02:00
2021-05-12 16:17:33 +02:00
toot_text + = " \n "
2021-05-14 13:14:31 +02:00
toot_text + = " top ten (soft users servers): " + " \n "
2021-05-12 16:17:33 +02:00
toot_text + = " \n "
2020-05-19 23:33:55 +02:00
2021-05-12 16:17:33 +02:00
i = 0
while i < 10 :
2020-05-19 23:33:55 +02:00
2021-05-12 16:17:33 +02:00
project_soft = soft_total_project [ i ]
project_users = soft_total_users [ i ]
project_servers = soft_total_servers [ i ]
len_pr_soft = len ( project_soft )
2020-05-19 23:33:55 +02:00
2021-05-12 16:17:33 +02:00
if project_soft == ' writefreely ' :
2020-05-19 23:33:55 +02:00
2021-05-12 16:17:33 +02:00
str_len = 11
2020-05-19 23:33:55 +02:00
2021-05-12 16:17:33 +02:00
else :
2020-05-19 23:33:55 +02:00
2021-05-12 16:17:33 +02:00
str_len = 13
2020-05-19 23:33:55 +02:00
2021-05-12 16:17:33 +02:00
toot_text + = f " { ' : ' + project_soft + ' : ' : <11 } " + f " { project_users : > { str_len } , } " + " " + f " { project_servers : >5, } " + " \n "
2020-05-19 23:33:55 +02:00
2021-05-12 16:17:33 +02:00
i + = 1
2020-05-19 23:33:55 +02:00
2021-05-12 16:17:33 +02:00
print ( " Tooting... " )
print ( toot_text )
2020-05-19 23:33:55 +02:00
2021-08-31 11:11:24 +02:00
servers_image_id = mastodon . media_post ( ' servers.png ' , " image/png " , description = ' servers graph ' ) . id
2021-05-12 16:17:33 +02:00
2021-08-31 11:11:24 +02:00
users_image_id = mastodon . media_post ( ' users.png ' , " image/png " , description = ' users graph ' ) . id
2020-05-19 23:33:55 +02:00
2021-05-12 16:17:33 +02:00
mastodon . status_post ( toot_text , in_reply_to_id = None , media_ids = { servers_image_id , users_image_id } )