kopia lustrzana https://github.com/dsblank/activitypub
Working webfinger, query arguments
rodzic
946e6219d4
commit
588798fae1
|
@ -6,29 +6,15 @@ try:
|
|||
except:
|
||||
def create_engine(*args, **kwargs):
|
||||
raise Exception("You need to install sqlalchemy")
|
||||
|
||||
|
||||
import logging
|
||||
import json
|
||||
|
||||
from ..bson import ObjectId
|
||||
from ..json import JSONDecoder, JSONEncoder
|
||||
from .base import Database
|
||||
from .listdb import ListTable
|
||||
|
||||
class JSONEncoder(json.JSONEncoder):
|
||||
def default(self, o):
|
||||
if isinstance(o, ObjectId):
|
||||
return {"$oid": str(o)}
|
||||
return super().default(o)
|
||||
|
||||
class JSONDecoder(json.JSONDecoder):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(object_hook=self.object_hook, *args, **kwargs)
|
||||
|
||||
def object_hook(self, obj):
|
||||
if '$oid' not in obj:
|
||||
return obj
|
||||
return ObjectId(obj['$oid'])
|
||||
|
||||
class SQLList():
|
||||
def __init__(self, database, name):
|
||||
self.database = database
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
import json
|
||||
|
||||
class JSONEncoder(json.JSONEncoder):
|
||||
def default(self, o):
|
||||
if isinstance(o, ObjectId):
|
||||
return {"$oid": str(o)}
|
||||
return super().default(o)
|
||||
|
||||
class JSONDecoder(json.JSONDecoder):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(object_hook=self.object_hook, *args, **kwargs)
|
||||
|
||||
def object_hook(self, obj):
|
||||
if '$oid' not in obj:
|
||||
return obj
|
||||
return ObjectId(obj['$oid'])
|
||||
|
|
@ -1,15 +1,19 @@
|
|||
import re
|
||||
|
||||
from .base import app
|
||||
|
||||
WEBFINGER = re.compile(r'(?:acct:)?(?P<username>[\w.!#$%&\'*+-/=?^_`{|}~]+)@(?P<host>[\w.:-]+)')
|
||||
|
||||
@app.route("/user/<nickname>", ["GET"])
|
||||
def route_user(self, nickname):
|
||||
#obj = self.database.actors.find(id=nickname)
|
||||
#obj = self.database.actors.find_one(id=nickname)
|
||||
obj = self.Actor(id=nickname)
|
||||
if obj:
|
||||
return self.render_json(
|
||||
obj.to_dict()
|
||||
)
|
||||
else:
|
||||
self.error(404)
|
||||
return self.error(404)
|
||||
|
||||
@app.route("/user/<nickname>/publickey", ["GET"])
|
||||
def route_publickey(self, nickname):
|
||||
|
@ -19,7 +23,7 @@ def route_publickey(self, nickname):
|
|||
obj.to_dict()
|
||||
)
|
||||
else:
|
||||
self.error(404)
|
||||
return self.error(404)
|
||||
|
||||
@app.route("/user/<nickname>/outbox", ["GET"])
|
||||
def route_user_outbox(self, nickname):
|
||||
|
@ -29,7 +33,7 @@ def route_user_outbox(self, nickname):
|
|||
obj.to_dict()
|
||||
)
|
||||
else:
|
||||
self.error(404)
|
||||
return self.error(404)
|
||||
|
||||
@app.route("/user/<nickname>/outbox/<page>", ["GET"])
|
||||
def route_outbox_page(self, nickname, page):
|
||||
|
@ -39,7 +43,7 @@ def route_outbox_page(self, nickname, page):
|
|||
obj.to_dict()
|
||||
)
|
||||
else:
|
||||
self.error(404)
|
||||
return self.error(404)
|
||||
|
||||
#@app.route("/user/<nickname>/outbox", ["POST"])
|
||||
#def route_(self):
|
||||
|
@ -53,7 +57,7 @@ def route_inbox(self, nickname):
|
|||
obj.to_dict()
|
||||
)
|
||||
else:
|
||||
self.error(404)
|
||||
return self.error(404)
|
||||
|
||||
@app.route("/user/<nickname>/inbox/<page>", ["GET"])
|
||||
def route_inbox_page(self, nickname, page):
|
||||
|
@ -63,7 +67,7 @@ def route_inbox_page(self, nickname, page):
|
|||
obj.to_dict()
|
||||
)
|
||||
else:
|
||||
self.error(404)
|
||||
return self.error(404)
|
||||
|
||||
#@app.route("/user/<nickname>/inbox", ["POST"])
|
||||
#def route_(self):
|
||||
|
@ -77,7 +81,7 @@ def route_followers(self, nickname):
|
|||
obj.to_dict()
|
||||
)
|
||||
else:
|
||||
self.error(404)
|
||||
return self.error(404)
|
||||
|
||||
@app.route("/user/<nickname>/followers/<page>", ["GET"])
|
||||
def route_followers_page(self, nickname, page):
|
||||
|
@ -87,7 +91,7 @@ def route_followers_page(self, nickname, page):
|
|||
obj.to_dict()
|
||||
)
|
||||
else:
|
||||
self.error(404)
|
||||
return self.error(404)
|
||||
|
||||
@app.route("/user/<nickname>/following", ["GET"])
|
||||
def route_following(self, nickname):
|
||||
|
@ -97,7 +101,7 @@ def route_following(self, nickname):
|
|||
obj.to_dict()
|
||||
)
|
||||
else:
|
||||
self.error(404)
|
||||
return self.error(404)
|
||||
|
||||
@app.route("/user/<nickname>/following/<page>", ["GET"])
|
||||
def route_following_page(self, nickname, page):
|
||||
|
@ -107,7 +111,7 @@ def route_following_page(self, nickname, page):
|
|||
obj.to_dict()
|
||||
)
|
||||
else:
|
||||
self.error(404)
|
||||
return self.error(404)
|
||||
|
||||
@app.route("/user/<nickname>/liked", ["GET"])
|
||||
def route_liked(self, nickname):
|
||||
|
@ -117,7 +121,7 @@ def route_liked(self, nickname):
|
|||
obj.to_dict()
|
||||
)
|
||||
else:
|
||||
self.error(404)
|
||||
return self.error(404)
|
||||
|
||||
@app.route("/user/<nickname>/liked/<page>", ["GET"])
|
||||
def route_liked_page(self, nickname, page):
|
||||
|
@ -127,7 +131,7 @@ def route_liked_page(self, nickname, page):
|
|||
obj.to_dict()
|
||||
)
|
||||
else:
|
||||
self.error(404)
|
||||
return self.error(404)
|
||||
|
||||
@app.route("/activity/<uuid>", ["GET"])
|
||||
def route_activity(self, uuid):
|
||||
|
@ -137,7 +141,7 @@ def route_activity(self, uuid):
|
|||
obj.to_dict()
|
||||
)
|
||||
else:
|
||||
self.error(404)
|
||||
return self.error(404)
|
||||
|
||||
@app.route("/activity/<uuid>/replies", ["GET"])
|
||||
def route_activity_replies(self, uuid):
|
||||
|
@ -147,7 +151,7 @@ def route_activity_replies(self, uuid):
|
|||
obj.to_dict()
|
||||
)
|
||||
else:
|
||||
self.error(404)
|
||||
return self.error(404)
|
||||
|
||||
@app.route("/activity/<uuid>/replies/<page>", ["GET"])
|
||||
def route_activity_replies_page(self, uuid, page):
|
||||
|
@ -157,7 +161,7 @@ def route_activity_replies_page(self, uuid, page):
|
|||
obj.to_dict()
|
||||
)
|
||||
else:
|
||||
self.error(404)
|
||||
return self.error(404)
|
||||
|
||||
@app.route("/activity/<uuid>/likes", ["GET"])
|
||||
def route_activity_likes(self, uuid):
|
||||
|
@ -167,7 +171,7 @@ def route_activity_likes(self, uuid):
|
|||
obj.to_dict()
|
||||
)
|
||||
else:
|
||||
self.error(404)
|
||||
return self.error(404)
|
||||
|
||||
@app.route("/activity/<uuid>/likes/<page>", ["GET"])
|
||||
def route_activity_likes_page(self, uuid, page):
|
||||
|
@ -177,7 +181,7 @@ def route_activity_likes_page(self, uuid, page):
|
|||
obj.to_dict()
|
||||
)
|
||||
else:
|
||||
self.error(404)
|
||||
return self.error(404)
|
||||
|
||||
@app.route("/activity/<uuid>/shares", ["GET"])
|
||||
def route_activity_shares(self, uuid):
|
||||
|
@ -187,7 +191,7 @@ def route_activity_shares(self, uuid):
|
|||
obj.to_dict()
|
||||
)
|
||||
else:
|
||||
self.error(404)
|
||||
return self.error(404)
|
||||
|
||||
@app.route("/activity/<uuid>/shares/<page>", ["GET"])
|
||||
def route_activity_shares_page(self, uuid, page):
|
||||
|
@ -197,7 +201,7 @@ def route_activity_shares_page(self, uuid, page):
|
|||
obj.to_dict()
|
||||
)
|
||||
else:
|
||||
self.error(404)
|
||||
return self.error(404)
|
||||
|
||||
@app.route("/content/<uuid>", ["GET"])
|
||||
def route_content(self, uuid):
|
||||
|
@ -250,3 +254,117 @@ def route_content_shares_page(self, uuid, page):
|
|||
uuid=uuid,
|
||||
page=page,
|
||||
)
|
||||
|
||||
@app.route("/.well-known/webfinger", ["GET"])
|
||||
def route_webfinger(self):
|
||||
"""
|
||||
?resource=acct:bob@my-example.com
|
||||
"""
|
||||
resource = self.get_argument("resource")
|
||||
obj = None
|
||||
if resource:
|
||||
matches = WEBFINGER.match(resource)
|
||||
if matches:
|
||||
username = matches["username"]
|
||||
host = matches["host"]
|
||||
id = "https://%s/%s" % (host, username)
|
||||
obj = self.database.actors.find_one({"id":id})
|
||||
## Add a temp person:
|
||||
#obj = self.Person(id="dsblank")
|
||||
#self.database.actors.insert_one(obj.to_dict())
|
||||
if obj:
|
||||
return self.render_json({
|
||||
"subject": resource,
|
||||
"links": [{
|
||||
"rel": "self",
|
||||
"type": "application/activity+json",
|
||||
"href": obj["id"]
|
||||
}]
|
||||
})
|
||||
else:
|
||||
return self.error(404)
|
||||
|
||||
"""
|
||||
|
||||
{
|
||||
"subject": "acct:will@willnorris.com",
|
||||
"aliases": [
|
||||
"mailto:will@willnorris.com",
|
||||
"https://willnorris.com/"
|
||||
],
|
||||
"links": [
|
||||
{
|
||||
"rel": "http://webfinger.net/rel/avatar",
|
||||
"href": "https://willnorris.com/logo.jpg",
|
||||
"type": "image/jpeg"
|
||||
},
|
||||
{
|
||||
"rel": "http://webfinger.net/rel/profile-page",
|
||||
"href": "https://willnorris.com/",
|
||||
"type": "text/html"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
{
|
||||
"subject": "acct:alice@my-example.com",
|
||||
"links": [
|
||||
{
|
||||
"rel": "self",
|
||||
"type": "application/activity+json",
|
||||
"href": "https://my-example.com/actor"
|
||||
}
|
||||
]
|
||||
}
|
||||
"""
|
||||
|
||||
# /api/v1/instance
|
||||
|
||||
"""
|
||||
{
|
||||
"uri":"mastodon.social",
|
||||
"title":"Mastodon",
|
||||
"description":"This page describes the mastodon.social \u003cem\u003einstance\u003c/em\u003e - wondering what Mastodon is? Check out \u003ca href=\"https://joinmastodon.org\"\u003ejoinmastodon.org\u003c/a\u003e instead! In essence, Mastodon is a decentralized, open source social network. This is just one part of the network, run by the main developers of the project \u003cimg draggable=\"false\" alt=\"🐘\" class=\"emojione\" src=\"https://mastodon.social/emoji/1f418.svg\" /\u003e It is not focused on any particular niche interest - everyone is welcome as long as you follow our code of conduct!",
|
||||
"email":"hello@joinmastodon.org",
|
||||
"version":"2.4.3",
|
||||
"urls": {
|
||||
"streaming_api":"wss://mastodon.social"
|
||||
},
|
||||
"stats": {
|
||||
"user_count":171746,
|
||||
"status_count":6467133,
|
||||
"domain_count":5177
|
||||
},
|
||||
"thumbnail":"https://files.mastodon.social/site_uploads/files/000/000/001/original/DN5wMUeVQAENPwp.jpg_large.jpeg",
|
||||
"languages":["en"],
|
||||
"contact_account": {
|
||||
"id":"1",
|
||||
"username":"Gargron",
|
||||
"acct":"Gargron",
|
||||
"display_name":"Eugen",
|
||||
"locked":false,
|
||||
"bot":false,
|
||||
"created_at":"2016-03-16T14:34:26.392Z",
|
||||
"note":"\u003cp\u003eDeveloper of Mastodon. 25\u003c/p\u003e",
|
||||
"url":"https://mastodon.social/@Gargron",
|
||||
"avatar":"https://files.mastodon.social/accounts/avatars/000/000/001/original/eb9e00274b135808.png",
|
||||
"avatar_static":"https://files.mastodon.social/accounts/avatars/000/000/001/original/eb9e00274b135808.png",
|
||||
"header":"https://files.mastodon.social/accounts/headers/000/000/001/original/af58e4df0e8b3e15.png",
|
||||
"header_static":"https://files.mastodon.social/accounts/headers/000/000/001/original/af58e4df0e8b3e15.png",
|
||||
"followers_count":92732,
|
||||
"following_count":530,
|
||||
"statuses_count":40388,
|
||||
"emojis":[],
|
||||
"fields":[
|
||||
{
|
||||
"name":"Patreon",
|
||||
"value":"\u003ca href=\"https://www.patreon.com/mastodon\" rel=\"me nofollow noopener\" target=\"_blank\"\u003e\u003cspan class=\"invisible\"\u003ehttps://www.\u003c/span\u003e\u003cspan class=\"\"\u003epatreon.com/mastodon\u003c/span\u003e\u003cspan class=\"invisible\"\u003e\u003c/span\u003e\u003c/a\u003e"
|
||||
},
|
||||
{
|
||||
"name":"Liberapay",
|
||||
"value":"\u003ca href=\"https://liberapay.com/Mastodon/\" rel=\"me nofollow noopener\" target=\"_blank\"\u003e\u003cspan class=\"invisible\"\u003ehttps://\u003c/span\u003e\u003cspan class=\"\"\u003eliberapay.com/Mastodon/\u003c/span\u003e\u003cspan class=\"invisible\"\u003e\u003c/span\u003e\u003c/a\u003e"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
|
|
@ -15,6 +15,7 @@ class DataWrapper():
|
|||
"""
|
||||
Instance for saving routes, filters, etc. for app.
|
||||
|
||||
>>> app.clear()
|
||||
>>> @app.filter
|
||||
... def upper(item):
|
||||
... return item.upper()
|
||||
|
@ -37,6 +38,9 @@ class DataWrapper():
|
|||
"""
|
||||
_data = Data()
|
||||
|
||||
def clear(self):
|
||||
self._data.clear()
|
||||
|
||||
def filter(self, f):
|
||||
"""
|
||||
Wrap a plain function/method to provide template function.
|
||||
|
@ -131,7 +135,7 @@ class Manager():
|
|||
pass
|
||||
|
||||
def error(self, error_number):
|
||||
self.render_template("%s.html" % error_number)
|
||||
return self.render_template("%s.html" % error_number)
|
||||
|
||||
@property
|
||||
def request(self):
|
||||
|
|
|
@ -17,6 +17,9 @@ class FlaskManager(Manager):
|
|||
def render_json(self, obj):
|
||||
return jsonify(obj) # has correct header type set
|
||||
|
||||
def get_argument(self, name, default_value=None):
|
||||
return request.args.get(name, default_value)
|
||||
|
||||
def render_template(self, template_name, **kwargs):
|
||||
## TODO : add context_processor
|
||||
q = {
|
||||
|
|
|
@ -19,7 +19,9 @@ def make_handler(f, manager, methods):
|
|||
class Handler(RequestHandler):
|
||||
def get(self, *args, **kwargs):
|
||||
self.database = manager.database
|
||||
## TODO: add these in a more dynamic manner?
|
||||
self.Actor = manager.Actor
|
||||
self.Person = manager.Person
|
||||
self.Activity = manager.Activity
|
||||
self.Note = manager.Note
|
||||
return f(self, *args, **kwargs)
|
||||
|
|
Ładowanie…
Reference in New Issue