Working webfinger, query arguments

master
Douglas Blank 2018-07-26 22:30:47 -04:00
rodzic 946e6219d4
commit 588798fae1
6 zmienionych plików z 167 dodań i 37 usunięć

Wyświetl plik

@ -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

Wyświetl plik

@ -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'])

Wyświetl plik

@ -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"
}
]
}
}
"""

Wyświetl plik

@ -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):

Wyświetl plik

@ -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 = {

Wyświetl plik

@ -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)