Browse Source

first push to the git

master
mb@mb 5 years ago
parent
commit
0a72d2ed2f
  1. 2
      .gitignore
  2. 6
      README.md
  3. BIN
      static/icons/icon.jpg
  4. 101
      tada.py
  5. 22
      templates/actor.json
  6. 11
      templates/webfinger.json

2
.gitignore

@ -0,0 +1,2 @@
*.pem
__pycache__

6
README.md

@ -1,3 +1,5 @@
# ap.flask
# AP test in Flask
This is a testing area! :)
an ActivityPub testing area in Flask

BIN
static/icons/icon.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

101
tada.py

@ -0,0 +1,101 @@
#!/usr/bin/env python3
import flask, os, json
# import functions
""" A basic ActivityPub server written in Flask, that listens to follow requests.
Based on this tutorial: https://blog.joinmastodon.org/2018/06/how-to-implement-a-basic-activitypub-server/ """
"""
AP
ActivityPub
AlternativeProtocol
A...P...
"""
# Config
DOMAIN = 'https://ap.virtualprivateserver.space'
# domain = 'http://localhost:5000' # for local testing only, ActivityPub doesn't allow the usage of http:// (it only accepts https://)
def publicKey():
if not os.path.exists('./public.pem'):
os.system('openssl genrsa -out private.pem 2048')
os.system('openssl rsa -in private.pem -outform PEM -pubout -out public.pem')
else:
publicKey = open('./public.pem', 'r').read()
PUBLICKEY = publicKey.replace('\n', '\\n') # JSON-LD doesn't want to work with linebreaks,
# but needs the \n character to know where to break the line ;)
return PUBLICKEY
INBOX = []
# Create the application.
APP = flask.Flask(__name__)
@APP.route('/', methods=['GET'])
def index():
""" Displays the index page accessible at '/' """
content = 'test - index ({})'.format(DOMAIN)
return content
@APP.route('/.well-known/webfinger', methods=['GET'])
def webfinger():
""" When you try to search for an account in eg. Mastodon,
this object is return, with a link pointing to a place
where more information about this user can be found. """
""" What is Webfinger? It is what allows us to ask a website,
Do you have a user with this username? and receive resource
links in response, with more information about this user. """
if flask.request.args.get('resource'):
query = flask.request.args.get('resource') # acct:alice@tada.club
actor = query.split(':')[1].split('@')[0] # alice
json = flask.render_template('webfinger.json', query=query, actor=actor, domain=DOMAIN)
resp = flask.Response(json, status=200, mimetype='application/json')
return resp
else:
return 'no query'
@APP.route('/users/<actor>', methods=['GET'])
def return_actor(actor):
""" This returns the actor.json object when somebody in the
Fediverse searches for this user. It returns the paths of
this user's inbox, its preferred username and the user's public key.
And also a profile icon (image) now! :) """
preferredUsername = actor # but could become a custom username, set by the user, stored in the database
# this preferredUsername doesn't show up yet in Mastodon ...
json = flask.render_template('actor.json', actor=actor, preferredUsername=preferredUsername, publicKey=publicKey(), domain=DOMAIN) # actor = alice
resp = flask.Response(json, status=200, mimetype='application/json')
return resp
@APP.route('/inspect')
def inspect():
return flask.Response(b'<br><br>'.join(INBOX), status=200)
@APP.route('/users/<actor>/inbox', methods=['GET', 'POST'])
def inbox(actor):
""" To post to this inbox, you could use curl:
$ curl -d '{"key" : "value"}' -H "Content-Type: application/json" -X POST http://localhost:5001/users/test/inbox
Or, with an actual Mastodon follow request:
$ curl -d '{"@context":["https://www.w3.org/ns/activitystreams","https://w3id.org/security/v1",{"manuallyApprovesFollowers":"as:manuallyApprovesFollowers","sensitive":"as:sensitive","movedTo":{"@id":"as:movedTo","@type":"@id"},"Hashtag":"as:Hashtag","ostatus":"http://ostatus.org#","atomUri":"ostatus:atomUri","inReplyToAtomUri":"ostatus:inReplyToAtomUri","conversation":"ostatus:conversation","toot":"http://joinmastodon.org/ns#","Emoji":"toot:Emoji","focalPoint":{"@container":"@list","@id":"toot:focalPoint"},"featured":{"@id":"toot:featured","@type":"@id"},"schema":"http://schema.org#","PropertyValue":"schema:PropertyValue","value":"schema:value"}],"id":"https://post.lurk.org/02d04ed5-dda6-48f3-a551-2e9c554de745","type":"Follow","actor":"https://post.lurk.org/users/manetta","object":"https://ap.virtualprivateserver.space/users/test","signature":{"type":"RsaSignature2017","creator":"https://post.lurk.org/users/manetta#main-key","created":"2018-11-28T16:15:35Z","signatureValue":"XUdBg+Zj9pkdOXlAYHhOtZlmU1Jdt63zwh2cXoJ8E8C1C+KvgGilkyfPTud9VNymVwdUQRl+YEW9KAZiiGaHb9H+tdVUr9BEkuR5E/tGehbMZr1sakC+qPehe4s3bRKEpJjTTJnTiSHaW7V6Qvr1u6+MVts6oj32az/ixuB/CfodSr3K/K+jZmmOl6SIUqX7Xg7xGwOxIsYaR7g9wbcJ4qyzKcTPZonPMsONq9/RSm3SeQBo7WO1FKlQiFxVP/y5eFaFP8GYDLZyK7Nj5kDL5TannfEpuF8f3oyTBErQhcFQYKcBZNbuaqX/WiIaGjtHIL2ctJe0Psb5Nfshx4MXmQ=="}}' -H "Content-Type: application/json" -X POST http://localhost:5001/users/test/inbox
"""
if flask.request.method == 'GET':
return '''This has been a <em>{}</em> request. <br>
It came with the following header: <br><br><em>{}</em><br><br>
You have searched for the actor <em>{}</em>. <br>
This is <em>{}</em>'s shared inbox: <br><br><em>{}</em>'''.format(flask.request.method, flask.request.headers, actor, DOMAIN, str(INBOX))
if flask.request.method == 'POST':
INBOX.append(flask.request.data)
return flask.Response(status=200)
if __name__ == '__main__':
APP.debug=True
APP.run(port=5001)

22
templates/actor.json

@ -0,0 +1,22 @@
{
"@context": [
"https://www.w3.org/ns/activitystreams",
"https://w3id.org/security/v1"
],
"id": "{{ domain }}/users/{{ actor }}",
"type": "Person",
"preferredUsername": "{{ preferredUsername }}",
"inbox": "{{ domain }}/users/{{ actor }}/inbox",
"publicKey": {
"id": "{{ domain }}/users/{{ actor }}#main-key",
"owner": "{{ domain }}/users/{{ actor }}",
"publicKeyPem": "{{ publicKey }}"
},
"icon": {
"type": "Image",
"mediaType": "image/jpg",
"url": "https://ap.virtualprivateserver.space/static/icons/icon.jpg"
}
}

11
templates/webfinger.json

@ -0,0 +1,11 @@
{
"subject": "{{ query }}",
"links": [
{
"rel": "self",
"type": "application/activity+json",
"href": "{{ domain }}/users/{{ actor }}"
}
]
}
Loading…
Cancel
Save