mirror of https://gitlab.com/bashrc2/epicyon
Plotting federated instances
parent
b1516507f8
commit
7b06a3b262
|
@ -144,6 +144,15 @@ To list the domains referenced in public posts:
|
||||||
python3 epicyon.py --postDomains nickname@domain
|
python3 epicyon.py --postDomains nickname@domain
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Plotting federated instances
|
||||||
|
|
||||||
|
To plot a set of federated instances, based upon a sample of handles on those instances:
|
||||||
|
|
||||||
|
``` bash
|
||||||
|
python3 epicyon.py --socnet nickname1@domain1,nickname2@domain2,nickname3@domain3
|
||||||
|
xdot socnet.dot
|
||||||
|
```
|
||||||
|
|
||||||
## Delete posts
|
## Delete posts
|
||||||
|
|
||||||
To delete a post which you wrote you must first know its url. It is usually something like:
|
To delete a post which you wrote you must first know its url. It is usually something like:
|
||||||
|
|
31
epicyon.py
31
epicyon.py
|
@ -67,6 +67,7 @@ from shares import sendUndoShareViaServer
|
||||||
from shares import addShare
|
from shares import addShare
|
||||||
from theme import setTheme
|
from theme import setTheme
|
||||||
from announce import sendAnnounceViaServer
|
from announce import sendAnnounceViaServer
|
||||||
|
from socnet import instancesGraph
|
||||||
import argparse
|
import argparse
|
||||||
|
|
||||||
|
|
||||||
|
@ -151,6 +152,10 @@ parser.add_argument('--postDomains', dest='postDomains', type=str,
|
||||||
default=None,
|
default=None,
|
||||||
help='Show domains referenced in public '
|
help='Show domains referenced in public '
|
||||||
'posts for the given handle')
|
'posts for the given handle')
|
||||||
|
parser.add_argument('--socnet', dest='socnet', type=str,
|
||||||
|
default=None,
|
||||||
|
help='Show dot diagram for social network '
|
||||||
|
'of federated instances')
|
||||||
parser.add_argument('--postsraw', dest='postsraw', type=str,
|
parser.add_argument('--postsraw', dest='postsraw', type=str,
|
||||||
default=None,
|
default=None,
|
||||||
help='Show raw json of posts for the given handle')
|
help='Show raw json of posts for the given handle')
|
||||||
|
@ -449,13 +454,35 @@ if args.postDomains:
|
||||||
elif args.gnunet:
|
elif args.gnunet:
|
||||||
proxyType = 'gnunet'
|
proxyType = 'gnunet'
|
||||||
domainList = []
|
domainList = []
|
||||||
domainList = getPublicPostDomains(baseDir, nickname, domain, False, True,
|
domainList = getPublicPostDomains(baseDir, nickname, domain,
|
||||||
proxyType, args.port, httpPrefix, debug,
|
proxyType, args.port,
|
||||||
|
httpPrefix, debug,
|
||||||
__version__, domainList)
|
__version__, domainList)
|
||||||
for postDomain in domainList:
|
for postDomain in domainList:
|
||||||
print(postDomain)
|
print(postDomain)
|
||||||
sys.exit()
|
sys.exit()
|
||||||
|
|
||||||
|
if args.socnet:
|
||||||
|
if ',' not in args.socnet:
|
||||||
|
print('Syntax: '
|
||||||
|
'--socnet nick1@domain1,nick2@domain2,nick3@domain3')
|
||||||
|
sys.exit()
|
||||||
|
|
||||||
|
if not args.http:
|
||||||
|
args.port = 443
|
||||||
|
proxyType = 'tor'
|
||||||
|
dotGraph = instancesGraph(baseDir, args.socnet,
|
||||||
|
proxyType, args.port,
|
||||||
|
httpPrefix, debug,
|
||||||
|
__version__)
|
||||||
|
try:
|
||||||
|
with open('socnet.dot', 'w') as fp:
|
||||||
|
fp.write(dotGraph)
|
||||||
|
print('Saved to socnet.dot')
|
||||||
|
except BaseException:
|
||||||
|
pass
|
||||||
|
sys.exit()
|
||||||
|
|
||||||
if args.postsraw:
|
if args.postsraw:
|
||||||
if '@' not in args.postsraw:
|
if '@' not in args.postsraw:
|
||||||
print('Syntax: --postsraw nickname@domain')
|
print('Syntax: --postsraw nickname@domain')
|
||||||
|
|
29
posts.py
29
posts.py
|
@ -146,11 +146,14 @@ def getUserUrl(wfRequest: {}) -> str:
|
||||||
|
|
||||||
def parseUserFeed(session, feedUrl: str, asHeader: {},
|
def parseUserFeed(session, feedUrl: str, asHeader: {},
|
||||||
projectVersion: str, httpPrefix: str,
|
projectVersion: str, httpPrefix: str,
|
||||||
domain: str) -> None:
|
domain: str,depth=0) -> {}:
|
||||||
|
if depth > 10:
|
||||||
|
return None
|
||||||
|
|
||||||
feedJson = getJson(session, feedUrl, asHeader, None,
|
feedJson = getJson(session, feedUrl, asHeader, None,
|
||||||
projectVersion, httpPrefix, domain)
|
projectVersion, httpPrefix, domain)
|
||||||
if not feedJson:
|
if not feedJson:
|
||||||
return
|
return None
|
||||||
|
|
||||||
if 'orderedItems' in feedJson:
|
if 'orderedItems' in feedJson:
|
||||||
for item in feedJson['orderedItems']:
|
for item in feedJson['orderedItems']:
|
||||||
|
@ -168,9 +171,10 @@ def parseUserFeed(session, feedUrl: str, asHeader: {},
|
||||||
userFeed = \
|
userFeed = \
|
||||||
parseUserFeed(session, nextUrl, asHeader,
|
parseUserFeed(session, nextUrl, asHeader,
|
||||||
projectVersion, httpPrefix,
|
projectVersion, httpPrefix,
|
||||||
domain)
|
domain, depth+1)
|
||||||
for item in userFeed:
|
if userFeed:
|
||||||
yield item
|
for item in userFeed:
|
||||||
|
yield item
|
||||||
elif isinstance(nextUrl, dict):
|
elif isinstance(nextUrl, dict):
|
||||||
userFeed = nextUrl
|
userFeed = nextUrl
|
||||||
if userFeed.get('orderedItems'):
|
if userFeed.get('orderedItems'):
|
||||||
|
@ -444,8 +448,8 @@ def getPostDomains(session, outboxUrl: str, maxPosts: int,
|
||||||
maxMentions: int,
|
maxMentions: int,
|
||||||
maxEmoji: int, maxAttachments: int,
|
maxEmoji: int, maxAttachments: int,
|
||||||
federationList: [],
|
federationList: [],
|
||||||
personCache: {}, raw: bool,
|
personCache: {},
|
||||||
simple: bool, debug: bool,
|
debug: bool,
|
||||||
projectVersion: str, httpPrefix: str,
|
projectVersion: str, httpPrefix: str,
|
||||||
domain: str, domainList=[]) -> []:
|
domain: str, domainList=[]) -> []:
|
||||||
"""Returns a list of domains referenced within public posts
|
"""Returns a list of domains referenced within public posts
|
||||||
|
@ -467,6 +471,9 @@ def getPostDomains(session, outboxUrl: str, maxPosts: int,
|
||||||
userFeed = parseUserFeed(session, outboxUrl, asHeader,
|
userFeed = parseUserFeed(session, outboxUrl, asHeader,
|
||||||
projectVersion, httpPrefix, domain)
|
projectVersion, httpPrefix, domain)
|
||||||
for item in userFeed:
|
for item in userFeed:
|
||||||
|
i += 1
|
||||||
|
if i > maxPosts:
|
||||||
|
break
|
||||||
if not item.get('object'):
|
if not item.get('object'):
|
||||||
continue
|
continue
|
||||||
if not isinstance(item['object'], dict):
|
if not isinstance(item['object'], dict):
|
||||||
|
@ -486,9 +493,6 @@ def getPostDomains(session, outboxUrl: str, maxPosts: int,
|
||||||
getDomainFromActor(tagItem['href'])
|
getDomainFromActor(tagItem['href'])
|
||||||
if postDomain not in postDomains:
|
if postDomain not in postDomains:
|
||||||
postDomains.append(postDomain)
|
postDomains.append(postDomain)
|
||||||
i += 1
|
|
||||||
if i == maxPosts:
|
|
||||||
break
|
|
||||||
return postDomains
|
return postDomains
|
||||||
|
|
||||||
|
|
||||||
|
@ -2986,8 +2990,7 @@ def getPublicPostsOfPerson(baseDir: str, nickname: str, domain: str,
|
||||||
|
|
||||||
|
|
||||||
def getPublicPostDomains(baseDir: str, nickname: str, domain: str,
|
def getPublicPostDomains(baseDir: str, nickname: str, domain: str,
|
||||||
raw: bool, simple: bool, proxyType: str,
|
proxyType: str, port: int, httpPrefix: str,
|
||||||
port: int, httpPrefix: str,
|
|
||||||
debug: bool, projectVersion: str,
|
debug: bool, projectVersion: str,
|
||||||
domainList=[]) -> []:
|
domainList=[]) -> []:
|
||||||
""" Returns a list of domains referenced within public posts
|
""" Returns a list of domains referenced within public posts
|
||||||
|
@ -3028,7 +3031,7 @@ def getPublicPostDomains(baseDir: str, nickname: str, domain: str,
|
||||||
postDomains = \
|
postDomains = \
|
||||||
getPostDomains(session, personUrl, 64, maxMentions, maxEmoji,
|
getPostDomains(session, personUrl, 64, maxMentions, maxEmoji,
|
||||||
maxAttachments, federationList,
|
maxAttachments, federationList,
|
||||||
personCache, raw, simple, debug,
|
personCache, debug,
|
||||||
projectVersion, httpPrefix, domain, domainList)
|
projectVersion, httpPrefix, domain, domainList)
|
||||||
postDomains.sort()
|
postDomains.sort()
|
||||||
return postDomains
|
return postDomains
|
||||||
|
|
|
@ -0,0 +1,83 @@
|
||||||
|
__filename__ = "socnet.py"
|
||||||
|
__author__ = "Bob Mottram"
|
||||||
|
__license__ = "AGPL3+"
|
||||||
|
__version__ = "1.1.0"
|
||||||
|
__maintainer__ = "Bob Mottram"
|
||||||
|
__email__ = "bob@freedombone.net"
|
||||||
|
__status__ = "Production"
|
||||||
|
|
||||||
|
from session import createSession
|
||||||
|
from webfinger import webfingerHandle
|
||||||
|
from posts import getPersonBox
|
||||||
|
from posts import getPostDomains
|
||||||
|
|
||||||
|
|
||||||
|
def instancesGraph(baseDir: str, handles: str,
|
||||||
|
proxyType: str,
|
||||||
|
port: int, httpPrefix: str,
|
||||||
|
debug: bool, projectVersion: str) -> str:
|
||||||
|
""" Returns a dot graph of federating instances
|
||||||
|
based upon a few sample handles.
|
||||||
|
The handles argument should contain a comma separated list
|
||||||
|
of handles on different instances
|
||||||
|
"""
|
||||||
|
dotGraphStr = 'digraph instances {\n'
|
||||||
|
if ',' not in handles:
|
||||||
|
return dotGraphStr + '}\n'
|
||||||
|
session = createSession(proxyType)
|
||||||
|
if not session:
|
||||||
|
return dotGraphStr + '}\n'
|
||||||
|
|
||||||
|
personCache = {}
|
||||||
|
cachedWebfingers = {}
|
||||||
|
federationList = []
|
||||||
|
maxMentions = 99
|
||||||
|
maxEmoji = 99
|
||||||
|
maxAttachments = 5
|
||||||
|
|
||||||
|
personHandles = handles.split(',')
|
||||||
|
for handle in personHandles:
|
||||||
|
handle = handle.strip()
|
||||||
|
if handle.startswith('@'):
|
||||||
|
handle = handle[1:]
|
||||||
|
if '@' not in handle:
|
||||||
|
continue
|
||||||
|
|
||||||
|
nickname = handle.split('@')[0]
|
||||||
|
domain = handle.split('@')[1]
|
||||||
|
|
||||||
|
domainFull = domain
|
||||||
|
if port:
|
||||||
|
if port != 80 and port != 443:
|
||||||
|
if ':' not in domain:
|
||||||
|
domainFull = domain + ':' + str(port)
|
||||||
|
handle = httpPrefix + "://" + domainFull + "/@" + nickname
|
||||||
|
wfRequest = \
|
||||||
|
webfingerHandle(session, handle, httpPrefix,
|
||||||
|
cachedWebfingers,
|
||||||
|
domain, projectVersion)
|
||||||
|
if not wfRequest:
|
||||||
|
return dotGraphStr + '}\n'
|
||||||
|
if not isinstance(wfRequest, dict):
|
||||||
|
print('Webfinger for ' + handle + ' did not return a dict. ' +
|
||||||
|
str(wfRequest))
|
||||||
|
return dotGraphStr + '}\n'
|
||||||
|
|
||||||
|
(personUrl, pubKeyId, pubKey,
|
||||||
|
personId, shaedInbox,
|
||||||
|
capabilityAcquisition,
|
||||||
|
avatarUrl, displayName) = getPersonBox(baseDir, session, wfRequest,
|
||||||
|
personCache,
|
||||||
|
projectVersion, httpPrefix,
|
||||||
|
nickname, domain, 'outbox')
|
||||||
|
postDomains = \
|
||||||
|
getPostDomains(session, personUrl, 64, maxMentions, maxEmoji,
|
||||||
|
maxAttachments, federationList,
|
||||||
|
personCache, debug,
|
||||||
|
projectVersion, httpPrefix, domain, [])
|
||||||
|
postDomains.sort()
|
||||||
|
for fedDomain in postDomains:
|
||||||
|
dotLineStr = ' "' + domain + '" -> "' + fedDomain + '";\n'
|
||||||
|
if dotLineStr not in dotGraphStr:
|
||||||
|
dotGraphStr += dotLineStr
|
||||||
|
return dotGraphStr + '}\n'
|
Loading…
Reference in New Issue