From 0ff65b483a3b5ca43d92b97b4847ab6f4509e63e Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Fri, 22 Jan 2021 11:29:36 +0000 Subject: [PATCH] Masto api account --- daemon.py | 45 ++++++++++++++++++++++++++++++++++++--------- mastoapiv1.py | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+), 9 deletions(-) create mode 100644 mastoapiv1.py diff --git a/daemon.py b/daemon.py index e9d3417e9..d55fd5a15 100644 --- a/daemon.py +++ b/daemon.py @@ -25,6 +25,7 @@ from webfinger import webfingerMeta from webfinger import webfingerNodeInfo from webfinger import webfingerLookup from webfinger import webfingerUpdate +from mastoapiv1 import getMastoApiV1Account from metadata import metaDataInstance from metadata import metaDataNodeInfo from pgp import getEmailAddress @@ -781,17 +782,37 @@ class PubServer(BaseHTTPRequestHandler): return True return False - def _mastoApiV1(self, callingDomain: str, authorized: bool) -> bool: + def _mastoApiV1(self, path: str, callingDomain: str, + authorized: bool, + baseDir: str, nickname: str, domain: str) -> bool: """This is a vestigil mastodon API for the purpose of returning an empty result to sites like https://mastopeek.app-dist.eu """ - if not self.path.startswith('/api/v1/'): + if not path.startswith('/api/v1/'): return False if self.server.debug: - print('DEBUG: mastodon api v1 ' + self.path) + print('DEBUG: mastodon api v1 ' + path) + if authorized and nickname: + if path == '/api/v1/accounts/:id': + acctJson = getMastoApiV1Account(baseDir, nickname, domain) + msg = json.dumps(instanceJson).encode('utf-8') + msglen = len(msg) + if self._hasAccept(callingDomain): + if 'application/ld+json' in self.headers['Accept']: + self._set_headers('application/ld+json', msglen, + None, callingDomain) + else: + self._set_headers('application/json', msglen, + None, callingDomain) + else: + self._set_headers('application/ld+json', msglen, + None, callingDomain) + self._write(msg) + print('masto API account sent for ' + nickname) + return True adminNickname = getConfigParam(self.server.baseDir, 'admin') - if adminNickname and self.path == '/api/v1/instance': + if adminNickname and path == '/api/v1/instance': instanceDescriptionShort = \ getConfigParam(self.server.baseDir, 'instanceDescriptionShort') @@ -829,7 +850,7 @@ class PubServer(BaseHTTPRequestHandler): self._write(msg) print('instance metadata sent') return True - if self.path.startswith('/api/v1/instance/peers'): + if path.startswith('/api/v1/instance/peers'): # This is just a dummy result. # Showing the full list of peers would have privacy implications. # On a large instance you are somewhat lost in the crowd, but on @@ -851,7 +872,7 @@ class PubServer(BaseHTTPRequestHandler): self._write(msg) print('instance peers metadata sent') return True - if self.path.startswith('/api/v1/instance/activity'): + if path.startswith('/api/v1/instance/activity'): # This is just a dummy result. msg = json.dumps([]).encode('utf-8') msglen = len(msg) @@ -871,8 +892,11 @@ class PubServer(BaseHTTPRequestHandler): self._404() return True - def _mastoApi(self, callingDomain: str, authorized: bool) -> bool: - return self._mastoApiV1(callingDomain, authorized) + def _mastoApi(self, path: str, callingDomain: str, + authorized: bool, + baseDir: str, nickname: str, domain: str) -> bool: + return self._mastoApiV1(path, callingDomain, authorized, + baseDir, nickname, domain) def _nodeinfo(self, callingDomain: str) -> bool: if not self.path.startswith('/nodeinfo/2.0'): @@ -9892,7 +9916,10 @@ class PubServer(BaseHTTPRequestHandler): 'show logout', 'isAuthorized') # minimal mastodon api - if self._mastoApi(callingDomain, authorized): + if self._mastoApi(self.path, callingDomain, authorized, + self.server.baseDir, + self.authorizedNickname, + self.server.domain): return self._benchmarkGETtimings(GETstartTime, GETtimings, diff --git a/mastoapiv1.py b/mastoapiv1.py new file mode 100644 index 000000000..5d0bc35fa --- /dev/null +++ b/mastoapiv1.py @@ -0,0 +1,42 @@ +__filename__ = "mastoapiv1.py" +__author__ = "Bob Mottram" +__license__ = "AGPL3+" +__version__ = "1.1.0" +__maintainer__ = "Bob Mottram" +__email__ = "bob@freedombone.net" +__status__ = "Production" + +import os +from utils import loadJson + + +def getMastoApiV1Account(baseDir: str, nickname: str, domain: str) -> {}: + """See https://github.com/McKael/mastodon-documentation/ + blob/master/Using-the-API/API.md#account + Authorization has already been performed + """ + accountFilename = \ + baseDir + '/accounts/' + nickname + '@' + domain + '.json' + if not os.path.isfile(accountFilename): + return {} + accountJson = loadJson(accountFilename) + if not accountJson: + return {} + mastoAccountJson = { + "id": accountJson['id'], + "username": nickname, + "acct": nickname, + "display_name": accountJson['preferredUsername'], + "locked": accountJson['manuallyApprovesFollowers'], +# "created_at": "", + "followers_count": 0, + "following_count": 0, + "statuses_count": 0, + "note": accountJson['summary'], + "url": accountJson['id'], + "avatar": accountJson['icon']['url'], + "avatar_static": accountJson['icon']['url'], + "header": accountJson['image']['url'], + "header_static": accountJson['image']['url'] + } + return mastoAccountJson