diff --git a/tildes/openapi_beta.yaml b/tildes/openapi_beta.yaml new file mode 100644 index 0000000..2a6d3a2 --- /dev/null +++ b/tildes/openapi_beta.yaml @@ -0,0 +1,282 @@ +openapi: 3.0.0 +info: + title: Tildes Beta API Schema + version: Beta + description: | + This is the OpenAPI schema for the Tildes Beta API. + The beta API is subject to change and may not be fully stable. + Future updates WILL include breaking changes. + Use at your own risk. +servers: + - url: /api/beta +paths: + /topics: + get: + summary: Get a list of topics + parameters: + - $ref: '#/components/parameters/paginationLimit' + - $ref: '#/components/parameters/paginationBefore' + - $ref: '#/components/parameters/paginationAfter' + - in: query + name: period + schema: + type: string + default: "all" + required: false + description: The time period for which to retrieve topics. For example 4h" or "2d". + - in: query + name: tag + schema: + type: string + required: false + description: The tag to filter topics by. If not specified, topics are not filtered on their tags. + - in: query + name: order + schema: + type: string + default: "activity" + enum: ["activity", "votes", "comments", "new", "all_activity"] + required: false + description: The sort order for the topics. Defaults to "activity". + responses: + "200": + description: A list of topics + content: + application/json: + schema: + type: object + required: + - topics + - pagination + properties: + topics: + type: array + items: + $ref: '#/components/schemas/Topic' + pagination: + $ref: '#/components/schemas/Pagination' + "400": + $ref: "#/components/responses/ValidationError" + + +components: + parameters: + paginationBefore: + in: query + name: before + schema: + type: string + required: false + description: The ID36 of the first item from the previous page, to get items before it. You can only specify either `before` or `after`, not both. + + paginationAfter: + in: query + name: after + schema: + type: string + required: false + description: The ID36 of the last item from the previous page, to get items after it. You can only specify either `before` or `after`, not both. + + paginationLimit: + in: query + name: limit + schema: + type: integer + minimum: 1 + maximum: 100 + default: 50 + required: false + description: The maximum number of items to return. The `limit` is itself limited to prevent abuse. + + responses: + ValidationError: + description: OpenAPI request/response validation failed + content: + application/json: + schema: + type: array + items: + $ref: "#/components/schemas/Error" + + schemas: + Topic: + type: object + required: + - id + - title + - text_html + - url + - comments_url + - group + - content_metadata + - created_at + - posted_by_user + - vote_count + - comment_count + - new_comment_count + - voted + - bookmarked + - ignored + - official + - tags + properties: + id: + type: integer + title: + type: string + text_html: + type: string + nullable: true + url: + type: string + nullable: true + comments_url: + type: string + source_site_name: + type: string + nullable: true + source_site_icon: + type: string + nullable: true + group: + type: string + content_metadata: + type: array + items: + type: string + created_at: + type: string + posted_by_user: + type: string + vote_count: + type: integer + comment_count: + type: integer + new_comment_count: + type: integer + nullable: true + voted: + type: boolean + nullable: true + bookmarked: + type: boolean + nullable: true + ignored: + type: boolean + nullable: true + official: + type: boolean + tags: + type: array + items: + type: string + + Comment: + type: object + required: + - id + - depth + - author + - group + - topic_id + - voted + - can_vote + - can_label + - can_edit + - can_reply + - body_html + - votes + - posted_datetime + - posted_datetime_abbreviated + - deleted + - removed + - collapsed + - collapsed_individual + - exemplary + - exemplary_reasons + - user_labels + - is_new + - is_by_op + properties: + id: + type: string + depth: + type: integer + author: + type: string + parent_author: + type: string + nullable: true + group: + type: string + topic_id: + type: string + voted: + type: boolean + can_vote: + type: boolean + can_label: + type: boolean + can_edit: + type: boolean + can_reply: + type: boolean + body_html: + type: string + votes: + type: integer + posted_datetime: + type: string + posted_datetime_abbreviated: + type: string + deleted: + type: boolean + removed: + type: boolean + collapsed: + type: boolean + collapsed_individual: + type: boolean + exemplary: + type: boolean + exemplary_reasons: + type: array + items: + type: string + user_labels: + type: array + items: + type: string + is_new: + type: boolean + is_by_op: + type: boolean + + Pagination: + type: object + required: + - num_items + - next_link + - prev_link + properties: + num_items: + type: integer + description: The number of items returned in this response. + next_link: + type: string + nullable: true + prev_link: + type: string + nullable: true + + Error: + type: object + required: + - message + properties: + field: + type: string + message: + type: string + exception: + type: string diff --git a/tildes/tildes/__init__.py b/tildes/tildes/__init__.py index 58e626f..7f9a6e7 100644 --- a/tildes/tildes/__init__.py +++ b/tildes/tildes/__init__.py @@ -18,6 +18,7 @@ def main(global_config: dict[str, str], **settings: str) -> PrefixMiddleware: config.include("cornice") config.include("pyramid_session_redis") config.include("pyramid_webassets") + config.include("pyramid_openapi3") # include database first so the session and querying are available config.include("tildes.database") diff --git a/tildes/tildes/routes.py b/tildes/tildes/routes.py index bd8b8f4..9593fa1 100644 --- a/tildes/tildes/routes.py +++ b/tildes/tildes/routes.py @@ -128,6 +128,11 @@ def includeme(config: Configurator) -> None: config.add_route("shortener_group", "/~{path}", factory=group_by_path) config.add_route("shortener_topic", "/{topic_id36}", factory=topic_by_id36) + # Routes for the JSON API + # We also provide a path for the full spec and the built-in swagger UI explorer + config.pyramid_openapi3_spec('openapi_beta.yaml', route='/api/beta/openapi.yaml') + config.pyramid_openapi3_add_explorer(route='/api/beta/ui') + def add_intercooler_routes(config: Configurator) -> None: """Set up all routes for the (internal-use) Intercooler API endpoints."""