diff --git a/README.md b/README.md index d5555bf..2ec30e2 100644 --- a/README.md +++ b/README.md @@ -4,3 +4,9 @@ Early prototype of bridging the [IndieWeb](https://indieweb.org/) to [AT Protocol](https://atproto.com/). License: This project is placed in the public domain. + + +### TODO + +* Decide whether to mirror the [`app.bsky` lexicons](https://github.com/bluesky-social/atproto/tree/main/lexicons/app/bsky) in this repo or [fetch them dynamically via `getSchema`](https://atproto.com/guides/lexicon#schema-distribution), which isn't live on [bsky.app](https://bsky.app/) yet. +* Support new lexicon format in lexrpc, eg app/bsky/embed/images.json, including `type` `object`, `ref`, etc. diff --git a/app.py b/app.py index bd36303..cbc3b62 100644 --- a/app.py +++ b/app.py @@ -1,9 +1,13 @@ """Main Flask application.""" +import json +import logging from pathlib import Path from flask import Flask from flask_caching import Cache import flask_gae_static +from lexrpc.server import Server +from lexrpc.flask_server import init_flask from oauth_dropins.webutil import ( appengine_info, appengine_config, @@ -11,11 +15,14 @@ from oauth_dropins.webutil import ( util, ) +logger = logging.getLogger(__name__) +app_dir = Path(__file__).parent +# Flask app app = Flask(__name__, static_folder=None) app.template_folder = './templates' app.json.compact = False -app.config.from_pyfile(Path(__file__).parent / 'config.py') +app.config.from_pyfile(app_dir / 'config.py') app.url_map.converters['regex'] = flask_util.RegexConverter app.after_request(flask_util.default_modern_headers) app.register_error_handler(Exception, flask_util.handle_exception) @@ -32,5 +39,18 @@ cache = Cache(app) util.set_user_agent('Bridgy AT (https://at.brid.gy/)') +# XRPC server +lexicons = [] +for filename in (app_dir / 'lexicons/app/bsky').glob('**/*.json'): + logger.debug(f'Loading lexicon from {filename}') + with open(filename) as f: + lexicon = json.load(f) + # TODO + # if lexicon.get('defs', {}).get('main', {}).get('type') in ('query', 'procedure'): + # lexicons.append(lexicon) +xrpc_server = Server(lexicons) +init_flask(xrpc_server, app) + +# import all modules to register their Flask handlers import pages diff --git a/lexicons b/lexicons new file mode 120000 index 0000000..58ce2ef --- /dev/null +++ b/lexicons @@ -0,0 +1 @@ +../atproto/lexicons \ No newline at end of file diff --git a/tests/test_xrpc_actor.py b/tests/test_xrpc_actor.py index 6ed633a..62c9955 100644 --- a/tests/test_xrpc_actor.py +++ b/tests/test_xrpc_actor.py @@ -1,4 +1,5 @@ """Unit tests for actor.py.""" +import app from . import testutil diff --git a/xrpc_actor.py b/xrpc_actor.py index db042aa..afbe34f 100644 --- a/xrpc_actor.py +++ b/xrpc_actor.py @@ -1,8 +1,38 @@ """app.bsky.actor.* XRPC methods.""" -# lexicons/app/bsky/actor/createScene.json -# lexicons/app/bsky/actor/getProfile.json -# lexicons/app/bsky/actor/getSuggestions.json -# lexicons/app/bsky/actor/search.json -# lexicons/app/bsky/actor/searchTypeahead.json -# lexicons/app/bsky/actor/updateProfile.json +@xrpc_server.method('app.bsky.actor.createScene') +def createScene(): + """ + lexicons/app/bsky/actor/createScene.json + """ + +@xrpc_server.method('app.bsky.actor.getProfile') +def getProfile(): + """ + lexicons/app/bsky/actor/getProfile.json + """ + +@xrpc_server.method('app.bsky.actor.getSuggestions') +def getSuggestions(): + """ + lexicons/app/bsky/actor/getSuggestions.json + """ + +@xrpc_server.method('app.bsky.actor.search') +def search(): + """ + lexicons/app/bsky/actor/search.json + """ + +@xrpc_server.method('app.bsky.actor.searchTypeahead') +def searchTypeahead(): + """ + lexicons/app/bsky/actor/searchTypeahead.json + """ + +@xrpc_server.method('app.bsky.actor.updateProfile') +def updateProfile(): + """ + lexicons/app/bsky/actor/updateProfile.json + """ + diff --git a/xrpc_feed.py b/xrpc_feed.py index 771fc0f..efba4a3 100644 --- a/xrpc_feed.py +++ b/xrpc_feed.py @@ -1,8 +1,39 @@ """app.bsky.feed.* XRPC methods.""" +from app import xrpc_server + +@xrpc_server.method('app.bsky.feed.getAuthorFeed') +def getAuthorFeed(): + """ + lexicons/app/bsky/feed/getAuthorFeed.json + """ + +@xrpc_server.method('app.bsky.feed.getPostThread') +def getPostThread(): + """ + lexicons/app/bsky/feed/getPostThread.json + """ + +@xrpc_server.method('app.bsky.feed.getRepostedBy') +def getRepostedBy(): + """ + lexicons/app/bsky/feed/getRepostedBy.json + """ + +@xrpc_server.method('app.bsky.feed.getTimeline') +def getTimeline(): + """ + lexicons/app/bsky/feed/getTimeline.json + """ + +@xrpc_server.method('app.bsky.feed.getVotes') +def getVotes(): + """ + lexicons/app/bsky/feed/getVotes.json + """ + +@xrpc_server.method('app.bsky.feed.setVote') +def setVote(): + """ + lexicons/app/bsky/feed/setVote.json + """ -# lexicons/app/bsky/feed/getAuthorFeed.json -# lexicons/app/bsky/feed/getPostThread.json -# lexicons/app/bsky/feed/getRepostedBy.json -# lexicons/app/bsky/feed/getTimeline.json -# lexicons/app/bsky/feed/getVotes.json -# lexicons/app/bsky/feed/setVote.json diff --git a/xrpc_graph.py b/xrpc_graph.py index 729a032..ddde2fa 100644 --- a/xrpc_graph.py +++ b/xrpc_graph.py @@ -1,7 +1,32 @@ """app.bsky.graph.* XRPC methods.""" -# lexicons/app/bsky/graph/getAssertions.json -# lexicons/app/bsky/graph/getFollowers.json -# lexicons/app/bsky/graph/getFollows.json -# lexicons/app/bsky/graph/getMembers.json -# lexicons/app/bsky/graph/getMemberships.json +@xrpc_server.method('app.bsky.graph.getAssertions') +def getAssertions(): + """ + lexicons/app/bsky/graph/getAssertions.json + """ + +@xrpc_server.method('app.bsky.graph.getFollowers') +def getFollowers(): + """ + lexicons/app/bsky/graph/getFollowers.json + """ + +@xrpc_server.method('app.bsky.graph.getFollows') +def getFollows(): + """ + lexicons/app/bsky/graph/getFollows.json + """ + +@xrpc_server.method('app.bsky.graph.getMembers') +def getMembers(): + """ + lexicons/app/bsky/graph/getMembers.json + """ + +@xrpc_server.method('app.bsky.graph.getMemberships') +def getMemberships(): + """ + lexicons/app/bsky/graph/getMemberships.json + """ +