kopia lustrzana https://github.com/snarfed/bridgy-fed
activitypub actor endpoint: fetch mf2, convert to AS
rodzic
3928147414
commit
60a3f7b1cb
|
@ -0,0 +1,51 @@
|
|||
# coding=utf-8
|
||||
"""Handles requests for ActivityPub endpoints: actors, inbox, etc.
|
||||
"""
|
||||
import json
|
||||
import logging
|
||||
|
||||
import appengine_config
|
||||
|
||||
from granary import microformats2
|
||||
import mf2py
|
||||
import mf2util
|
||||
import requests
|
||||
import webapp2
|
||||
|
||||
|
||||
# https://www.w3.org/TR/activitypub/#retrieving-objects
|
||||
CONTENT_TYPE = 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"'
|
||||
USER_AGENT = 'bridgy-activitypub (https://activitypub.brid.gy/)'
|
||||
|
||||
|
||||
class ActorHandler(webapp2.RequestHandler):
|
||||
"""Serves /[DOMAIN], fetches its mf2, converts to AS Actor, and serves it."""
|
||||
|
||||
def get(self, domain):
|
||||
url = 'https://%s/' % domain
|
||||
resp = requests.get(url=url, headers={
|
||||
'User-Agent': USER_AGENT,
|
||||
})
|
||||
resp.raise_for_status()
|
||||
mf2 = mf2py.parse(resp.text, url=resp.url)
|
||||
logging.info('Parsed mf2 for %s: %s', resp.url, json.dumps(mf2, indent=2))
|
||||
|
||||
hcard = mf2util.representative_hcard(mf2, resp.url)
|
||||
logging.info('Representative h-card: %s', json.dumps(hcard, indent=2))
|
||||
|
||||
obj = microformats2.json_to_object(hcard)
|
||||
obj.update({
|
||||
'inbox': '%s/%s/inbox' % (self.request.host_url, domain),
|
||||
})
|
||||
logging.info('Returning: %s', json.dumps(obj, indent=2))
|
||||
|
||||
self.response.headers.update({
|
||||
'Content-Type': CONTENT_TYPE,
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
})
|
||||
self.response.write(json.dumps(obj, indent=2))
|
||||
|
||||
|
||||
app = webapp2.WSGIApplication(
|
||||
[(r'/([^/]+\.[^/]+)/?', ActorHandler),
|
||||
], debug=appengine_config.DEBUG)
|
6
app.yaml
6
app.yaml
|
@ -10,6 +10,8 @@ builtins:
|
|||
- remote_api: on
|
||||
|
||||
libraries:
|
||||
- name: lxml
|
||||
version: latest
|
||||
- name: ssl
|
||||
version: latest
|
||||
- name: webob
|
||||
|
@ -33,8 +35,8 @@ handlers:
|
|||
upload: static/index.html
|
||||
|
||||
# dynamic
|
||||
- url: /[^/]+
|
||||
script: app.application
|
||||
- url: /[^/]+/?
|
||||
script: activitypub.app
|
||||
secure: always
|
||||
|
||||
skip_files:
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
granary
|
||||
mf2py>=1.0.4
|
||||
mf2util>=0.5.0
|
||||
mock
|
||||
requests==2.10.0
|
||||
requests-toolbelt==0.6.2
|
||||
-e git+https://github.com/snarfed/webmention-tools.git#egg=webmentiontools
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
# webutil/test/__init__.py has setup code that makes App Engine SDK's
|
||||
# bundled libraries importable.
|
||||
import oauth_dropins.webutil.test
|
|
@ -0,0 +1,38 @@
|
|||
# coding=utf-8
|
||||
"""Unit tests for activitypub.py.
|
||||
"""
|
||||
import json
|
||||
import unittest
|
||||
|
||||
import mock
|
||||
import requests
|
||||
|
||||
import activitypub
|
||||
|
||||
|
||||
@mock.patch('requests.get')
|
||||
class ActivityPubTest(unittest.TestCase):
|
||||
|
||||
def test_actor_handler(self, mock_get):
|
||||
html = u"""
|
||||
<body>
|
||||
<a class="h-card" rel="me" href="/about-me">Mrs. ☕ Foo</a>
|
||||
</body>
|
||||
"""
|
||||
resp = requests.Response()
|
||||
resp.status_code = 200
|
||||
resp._text = html
|
||||
resp._content = html.encode('utf-8')
|
||||
resp.encoding = 'utf-8'
|
||||
resp.url = 'https://foo.com/'
|
||||
mock_get.return_value = resp
|
||||
|
||||
got = activitypub.app.get_response('/foo.com')
|
||||
self.assertEquals(200, got.status_int)
|
||||
self.assertEquals(activitypub.CONTENT_TYPE, got.headers['Content-Type'])
|
||||
self.assertEquals({
|
||||
'objectType' : 'person',
|
||||
'displayName': u'Mrs. ☕ Foo',
|
||||
'url': 'https://foo.com/about-me',
|
||||
'inbox': 'http://localhost/foo.com/inbox',
|
||||
}, json.loads(got.body))
|
Ładowanie…
Reference in New Issue