# retoor <retoor@molodetz.nl>
ROLE_LABELS = {"public": "Public", "user": "Member"}
def field(name, location, type="string", required=False, example="", description="", options=None):
spec = {
"name": name,
"location": location,
"type": type,
"required": required,
"example": example,
"description": description,
}
if options:
spec["options"] = list(options)
return spec
def endpoint(
id,
method,
path,
title,
summary,
auth="user",
encoding="none",
destructive=False,
params=None,
sample_response=None,
):
return {
"id": id,
"method": method,
"path": path,
"title": title,
"summary": summary,
"auth": auth,
"min_role": ROLE_LABELS.get(auth, auth.title()),
"encoding": encoding,
"destructive": destructive,
"params": params or [],
"sample_response": sample_response,
}
AUTH_TOKEN_SAMPLE = {
"success": True,
"auth_token": {"id": 18966518, "key": "z6uXRZrQ...", "expire_time": 1782024794, "user_id": 42},
}
RANT_SAMPLE = {
"id": 1,
"text": "My first rant about Python",
"score": 3,
"created_time": 1781419994,
"attached_image": "",
"num_comments": 2,
"tags": ["python", "devrant"],
"vote_state": 0,
"edited": False,
"link": "rants/1/my-first-rant-about-python",
"rt": 1,
"rc": 0,
"user_id": 42,
"user_username": "alice",
"user_score": 17,
"user_avatar": {"b": "5c47fe", "i": "u/alice.png"},
"user_avatar_lg": {"b": "5c47fe", "i": "u/alice.png"},
"editable": False,
}
COMMENT_SAMPLE = {
"id": 9,
"rant_id": 1,
"body": "Nice rant!",
"score": 0,
"created_time": 1781420050,
"vote_state": 0,
"user_id": 7,
"user_username": "bob",
"user_score": 4,
"user_avatar": {"b": "1188ff", "i": "u/bob.png"},
}
DEVRANT_GROUPS = {
"devrant-auth": [
endpoint(
"devrant-login",
"POST",
"/api/users/auth-token",
"Log in",
"Authenticate with username (or email) and password. Running this here logs you in for every widget on these pages.",
auth="public",
encoding="form",
params=[
field("username", "body", required=True, example="YOUR_USERNAME", description="Username or email."),
field("password", "body", type="password", required=True, example="", description="Account password."),
],
sample_response=AUTH_TOKEN_SAMPLE,
),
endpoint(
"devrant-register",
"POST",
"/api/users",
"Register",
"Create a new account. Returns an auth token (you are logged in immediately).",
auth="public",
encoding="form",
params=[
field("username", "body", required=True, example="newdev", description="3-32 letters, numbers, hyphens, underscores."),
field("email", "body", required=True, example="newdev@example.com", description="Valid email address."),
field("password", "body", type="password", required=True, example="", description="At least 6 characters."),
],
sample_response=AUTH_TOKEN_SAMPLE,
),
endpoint(
"devrant-delete-account",
"DELETE",
"/api/users/me",
"Deactivate account",
"Deactivate the logged-in account and revoke its tokens.",
auth="user",
destructive=True,
sample_response={"success": True},
),
],
"devrant-rants": [
endpoint(
"devrant-feed",
"GET",
"/api/devrant/rants",
"Rant feed",
"List rants. Sort by recent, top, or algo.",
auth="public",
params=[
field("sort", "query", type="enum", example="recent", options=["recent", "top", "algo"], description="Sort order."),
field("limit", "query", type="int", example="20", description="Page size, 1-50."),
field("skip", "query", type="int", example="0", description="Offset for pagination."),
],
sample_response={"success": True, "rants": [RANT_SAMPLE], "num_notifs": 0},
),
endpoint(
"devrant-get-rant",
"GET",
"/api/devrant/rants/{rant_id}",
"Single rant with comments",
"Fetch one rant and its comments.",
auth="public",
params=[field("rant_id", "path", type="int", required=True, example="1", description="Rant id.")],
sample_response={"success": True, "rant": RANT_SAMPLE, "comments": [COMMENT_SAMPLE], "subscribed": 0},
),
endpoint(
"devrant-create-rant",
"POST",
"/api/devrant/rants",
"Post a rant",
"Create a new rant. Tags are comma-separated and stored verbatim.",
auth="user",
encoding="form",
params=[
field("rant", "body", type="textarea", required=True, example="Posted from the docs widget", description="Rant text, 1-125000 chars."),
field("tags", "body", example="python,devrant", description="Comma-separated tags."),
],
sample_response={"success": True, "rant_id": 12},
),
endpoint(
"devrant-edit-rant",
"POST",
"/api/devrant/rants/{rant_id}",
"Edit a rant",
"Replace a rant's text and tags (owner only).",
auth="user",
encoding="form",
params=[
field("rant_id", "path", type="int", required=True, example="1", description="Rant id."),
field("rant", "body", type="textarea", required=True, example="Edited text", description="New rant text."),
field("tags", "body", example="python", description="Comma-separated tags."),
],
sample_response={"success": True},
),
endpoint(
"devrant-delete-rant",
"DELETE",
"/api/devrant/rants/{rant_id}",
"Delete a rant",
"Soft-delete a rant (owner or admin).",
auth="user",
destructive=True,
params=[field("rant_id", "path", type="int", required=True, example="1", description="Rant id.")],
sample_response={"success": True},
),
endpoint(
"devrant-vote-rant",
"POST",
"/api/devrant/rants/{rant_id}/vote",
"Vote on a rant",
"Upvote (1), downvote (-1), or clear (0). Returns the updated rant.",
auth="user",
encoding="form",
params=[
field("rant_id", "path", type="int", required=True, example="1", description="Rant id."),
field("vote", "body", type="enum", required=True, example="1", options=["1", "-1", "0"], description="Vote value."),
],
sample_response={"success": True, "rant": RANT_SAMPLE},
),
endpoint(
"devrant-favorite",
"POST",
"/api/devrant/rants/{rant_id}/favorite",
"Favorite a rant",
"Bookmark a rant.",
auth="user",
encoding="form",
params=[field("rant_id", "path", type="int", required=True, example="1", description="Rant id.")],
sample_response={"success": True},
),
endpoint(
"devrant-unfavorite",
"POST",
"/api/devrant/rants/{rant_id}/unfavorite",
"Unfavorite a rant",
"Remove a rant bookmark.",
auth="user",
encoding="form",
params=[field("rant_id", "path", type="int", required=True, example="1", description="Rant id.")],
sample_response={"success": True},
),
endpoint(
"devrant-comment-rant",
"POST",
"/api/devrant/rants/{rant_id}/comments",
"Comment on a rant",
"Post a comment on a rant.",
auth="user",
encoding="form",
params=[
field("rant_id", "path", type="int", required=True, example="1", description="Rant id."),
field("comment", "body", type="textarea", required=True, example="Great rant!", description="Comment text, 1-1000 chars."),
],
sample_response={"success": True},
),
endpoint(
"devrant-search",
"GET",
"/api/devrant/search",
"Search rants",
"Search rants by text in the title and body.",
auth="public",
params=[field("term", "query", required=True, example="python", description="Search text.")],
sample_response={"success": True, "results": [RANT_SAMPLE]},
),
],
"devrant-comments": [
endpoint(
"devrant-get-comment",
"GET",
"/api/comments/{comment_id}",
"Get a comment",
"Fetch a single comment by id.",
auth="public",
params=[field("comment_id", "path", type="int", required=True, example="1", description="Comment id.")],
sample_response={"success": True, "comment": COMMENT_SAMPLE},
),
endpoint(
"devrant-edit-comment",
"POST",
"/api/comments/{comment_id}",
"Edit a comment",
"Replace a comment's text (owner only).",
auth="user",
encoding="form",
params=[
field("comment_id", "path", type="int", required=True, example="1", description="Comment id."),
field("comment", "body", type="textarea", required=True, example="Edited comment", description="New comment text."),
],
sample_response={"success": True},
),
endpoint(
"devrant-delete-comment",
"DELETE",
"/api/comments/{comment_id}",
"Delete a comment",
"Soft-delete a comment (owner or admin).",
auth="user",
destructive=True,
params=[field("comment_id", "path", type="int", required=True, example="1", description="Comment id.")],
sample_response={"success": True},
),
endpoint(
"devrant-vote-comment",
"POST",
"/api/comments/{comment_id}/vote",
"Vote on a comment",
"Upvote (1), downvote (-1), or clear (0).",
auth="user",
encoding="form",
params=[
field("comment_id", "path", type="int", required=True, example="1", description="Comment id."),
field("vote", "body", type="enum", required=True, example="1", options=["1", "-1", "0"], description="Vote value."),
],
sample_response={"success": True},
),
],
"devrant-users": [
endpoint(
"devrant-get-user-id",
"GET",
"/api/get-user-id",
"Resolve username to id",
"Look up a user's integer id from their username.",
auth="public",
params=[field("username", "query", required=True, example="alice", description="Username to look up.")],
sample_response={"success": True, "user_id": 42},
),
endpoint(
"devrant-profile",
"GET",
"/api/users/{user_id}",
"Get a profile",
"Fetch a user's devRant profile with their rants and comments.",
auth="public",
params=[field("user_id", "path", type="int", required=True, example="1", description="User id.")],
sample_response={
"success": True,
"profile": {
"username": "alice",
"score": 17,
"about": "I build things with Python",
"location": "Amsterdam",
"created_time": 1781419994,
"skills": "I build things with Python",
"github": "alice",
"website": "https://alice.dev",
"avatar": {"b": "5c47fe", "i": "u/alice.png"},
"content": {
"content": {"rants": [RANT_SAMPLE], "upvoted": [], "comments": [COMMENT_SAMPLE], "favorites": [], "viewed": []},
"counts": {"rants": 1, "upvoted": 0, "comments": 1, "favorites": 0, "collabs": 0},
},
},
},
),
endpoint(
"devrant-edit-profile",
"POST",
"/api/users/me/edit-profile",
"Edit your profile",
"Update bio, location, git link, and website. profile_skills is accepted but ignored (skills are derived from the bio).",
auth="user",
encoding="form",
params=[
field("profile_about", "body", type="textarea", example="I build with Python and Rust", description="Bio."),
field("profile_location", "body", example="Amsterdam", description="Location."),
field("profile_github", "body", example="alice", description="Git link."),
field("profile_website", "body", example="https://alice.dev", description="Website."),
],
sample_response={"success": True},
),
],
"devrant-notifications": [
endpoint(
"devrant-notif-feed",
"GET",
"/api/users/me/notif-feed",
"Notification feed",
"Fetch the logged-in user's notification feed with unread counts.",
auth="user",
sample_response={
"success": True,
"data": {
"items": [{"type": "comment_discuss", "rant_id": 0, "comment_id": 0, "created_time": 1781420050, "read": 0, "uid": 7, "username": "bob"}],
"check_time": 1781420060,
"username_map": {"7": "bob"},
"unread": {"all": 1, "upvotes": 0, "mentions": 0, "comments": 1, "subs": 0, "total": 1},
"num_unread": 1,
},
},
),
endpoint(
"devrant-clear-notif-feed",
"DELETE",
"/api/users/me/notif-feed",
"Clear notifications",
"Mark every notification read.",
auth="user",
destructive=True,
sample_response={"success": True},
),
],
}
def devrant_endpoints(slug: str) -> list:
return DEVRANT_GROUPS.get(slug, [])