Models
Post
{
title: String,
url: String,
user: 'username',
score: Number,
date: Number,
content: String,
type: String,
tags: Array('postTag')
}
PostTag
postTag: {
tag: 'tag',
post: 'post',
score: Number
}
PostTagVote
postTagVote: {
tag: 'tag',
post: 'post',
user: 'username',
score: Number
}
Tag
tag: {
name: String,
count: Number
}
Comment
comment: {
id: String
time: Number,
post: 'post',
parent: 'comment'
childCount: Number,
content: String,
user: 'username',
upvotes: Number,
downvotes: Number,
threadUpvotes: Number,
threadDownvotes: Number
}
CommentVote
commentVote: {
comment: 'comment',
post: 'post',
user: 'user',
date: Date,
positive: Boolean
}
Posts API
GET /posts
Returns 100 posts.
Parameters
Offsets the responses by a set number.
Returns posts sorted by a particular algorithm.
-
popular default
Posts are sorted by score, within a time span between now and the requesting user's last login, or 24 hours, whichever is longer.
-
new
Posts are sorted by date. Newest first.
-
top
Posts are sorted by score. Highest first.
Only returns posts that were created within a specific time period.
-
all default
No time constraints.
-
day
Only returns posts created in the last day.
-
week
Only returns posts created in the last week.
-
month
Only returns posts created in the last month.
-
year
Only returns posts created in the last year.
Only returns results that match a specific tag. Multiple tags can be listed by separating tags with a +. If more than one tag is listed, it will return posts that match any of the tags. As an example:
/posts?tag=funny+wtf
will return 100 posts that either have a tag of funny or wtf.
Only returns results posts that were made by a specific user.
Requirements
-
Authentication
With no auth, should return401 Unauthorized
Example response
{
posts: [
{
"id": 2,
"title": "test post",
"user": "wombodombo",
"time": "1577171754000",
"url": "this_is_crazy",
"link": "", //optional
"content": "{\"ops\":[{\"insert\":\"This is a cool photo.\\n\"}]}", //quilljs formatted content
"type": "image",
"score": 148,
"commentCount": 21,
"width": 1920, //will appear for video and image content
"height": 1080, //will appear for video and image content
"tags": [
{
"tag": "funny",
"score": 10,
},
{
"tag": "meme",
"score": 7,
},
{
"tag": "image",
"score": 4,
}
]
},
// ...etc
]
}
GET /post/view/:url
Returns the data for a single post, referenced by its url. The date for the tags is the date the postTag association was first created.
Requirements
None. Should be available publicly
Example response
{
"id": 2,
"title": "test post",
"user": "wombodombo",
"time": "1577171754000",
"url": "this_is_crazy",
"link": "", //optional
"content": "{\"ops\":[{\"insert\":\"This is a cool photo.\\n\"}]}", //quilljs formatted content
"type": "image",
"score": 148,
"commentCount": 21,
"width": 1920, //will appear for video and image content
"height": 1080, //will appear for video and image content
"tags": [
{
"tag": "funny",
"score": 10,
},
{
"tag": "meme",
"score": 7,
},
{
"tag": "image",
"score": 4,
}
]
}
POST /post/create
Accepts a JSON payload to create a new post in the database
Requirements
Authentication
With no auth, should return401 Unauthorized
Example payload
{
"title": "My Cool Post!",
"url": "my-neato-post-wow",
"content": "This is the long form content for this post...",
"type": "blog"
}
Example response
{
"title": "My Cool Post!",
"user": "lapubell",
"time": "1577171754000",
"url": "my-neto-post-wow",
"tags": []
}
GET /post/url-is-available/:url
Returns a boolean based on if the requested URL is available
Requirements
None. Should be available publicly
Example response
true
Tags API
GET /tags
Should return 100 tags, sorted by number of postTags for that tag that have been created between now and the requesting user's last login, or one month, whichever is longer. The number of postTags for that tag should be populated into the "count" field.
Example response
{
"tags": [
{
"tag": "art",
"count": 4849,
},
{
"tag": "funny",
"count": 382,
},
// ...etc
}
]
}
PostTags API
POST/posttag/create
Adds a tag to a post.
Requirements
-
Authentication
With no auth, should return401 Unauthorized
Example payload
{
"post": "a-cool-painting",
"tag": "art",
}
Example response
{
"post": "a-cool-painting",
"tag": "art",
"score": 1
}
POST/posttag/add-vote
Adds a vote for a posttag.
Requirements
-
Authentication
With no auth, should return401 Unauthorized
Example payload
{
"post": "a-cool-painting",
"tag": "art",
}
Example response
{
"post": "a-cool-painting",
"tag": "art",
"score": 41
}
POST/posttag/remove-vote
Removes an existing vote for a posttag. If it is the only vote for it, this action also removes the posttag.
Requirements
-
Authentication
With no auth, should return401 Unauthorized
Example payload
{
"post": "a-cool-painting",
"tag": "art",
}
Example response
{
"post": "a-cool-painting",
"tag": "art",
"score": 40
}
Comments API
GET /comments/post/:post
Should return 100 comments for a specific post.
Parameters
Offsets the responses by a set number.
Returns comments sorted by a particular algorithm.
-
popular default
Comments are sorted by threadUpvotes. Highest first.
-
new
Comments are sorted by date. Newest first.
Example response
{
"comments": [
{
"id": "YPGpbT",
"time": "1577171754000",
"post": "this_is_crazy",
"parent": null,
"childCount": 4,
"content": "I really like this",
"user": "bojackson",
"upvotes": 144,
"downvotes": 38,
"threadUpvotes": 188,
"threadDownvotes": 22
},
{
"id": "qc33cG",
"time": "1577171754000",
"post": "this_is_crazy",
"parent": null,
"childCount": 0,
"content": "How neat!",
"user": "mamadisco",
"upvotes": 42,
"downvotes": 7,
"threadUpvotes": 42,
"threadDownvotes": 7
},
...etc
]
}
GET /comments/user/:user
Should return 100 comments for a specific user.
Parameters
Offsets the responses by a set number.
Returns comments sorted by a particular algorithm.
-
popular default
Comments are sorted by (upvotes - downvotes). Highest first.
-
new
Comments are sorted by date. Newest first.
Example response
{
"comments": [
{
"id": "YPGpbT",
"time": "1577171754000",
"post": "this_is_crazy",
"parent": null,
"childCount": 4,
"content": "I really like this",
"user": "jjcm",
"upvotes": 144,
"downvotes": 38,
"threadUpvotes": 188,
"threadDownvotes": 22
},
{
"id": "qc33cG",
"time": "1577171754000",
"post": "rickroll",
"parent": null,
"childCount": 0,
"content": "my fav song",
"user": "jjcm",
"upvotes": 42,
"downvotes": 7,
"threadUpvotes": 42,
"threadDownvotes": 7
},
...etc
]
}
GET /comments/comment/:comment
Should return 100 replies for a specific comment.
Parameters
Offsets the responses by a set number.
Returns comments sorted by a particular algorithm.
-
popular default
Comments are sorted by threadUpvotes. Highest first.
-
new
Comments are sorted by date. Newest first.
Example response
{
"comments": [
{
"id": "YPGpbT",
"time": "1577171754000",
"post": "this_is_crazy",
"parent": "GhB83c",
"childCount": 4,
"content": "I really like this",
"user": "bojackson",
"upvotes": 144,
"downvotes": 38,
"threadUpvotes": 188,
"threadDownvotes": 22
},
{
"id": "qc33cG",
"time": "1577171754000",
"post": "this_is_crazy",
"parent": "GhB83c",
"childCount": 0,
"content": "How neat!",
"user": "mamadisco",
"upvotes": 42,
"downvotes": 7,
"threadUpvotes": 42,
"threadDownvotes": 7
},
...etc
]
}
POST /comment/create
Allows the creation of a comment on a specific post. Can either be a top level comment or a reply to an existing comment.
Example payload
{
post: "this_is_crazy",
parent: null,
content: "Hey this is a comment!",
}
Example response
{
"id": "qc33cG",
"time": "1577171754000",
"post": "this_is_crazy",
"parent": null,
"childCount": 0,
"content": "How neat!",
"user": "jjcm",
"upvotes": 0,
"downvotes": 0,
"threadUpvotes": 0,
"threadDownvotes": 0
}
POST /comment/update/:comment
Allows for the update of a specific comment. Comment must be made by the user updating it.
Example payload
{
post: "this_is_crazy",
parent: null,
content: "Hey this is a *cool* comment!",
}
Example response
{
"id": "qc33cG",
"time": "1577171754000",
"post": "this_is_crazy",
"parent": null,
"childCount": 0,
"content": "How neat!",
"user": "jjcm",
"upvotes": 0,
"downvotes": 0,
"threadUpvotes": 0,
"threadDownvotes": 0
}
POST /comment/delete/:comment
Deletes a specific comment. Comment must be made by the user deleting it.
Example response
true
User API
POST /user/login
Logs the user in. Returns a JWT.
Example payload
{
"email": "jjcm@non.io",
"password": "hunter2"
}
Example response
{
"accessToken":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6ImFzZGZAYXNkZi5jb20iLCJleHBpcmVzQXQiOjE1ODMxNDc1NDh9.okbK22xZYZFk19K_NwLd7g48mxQZfWR5filMadonSe8",
"refreshToken":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6ImpAampjbS5vcmciLCJleHBpcmVzQXQiOjE3NDQ2NzE2MjksInR5cGUiOiJyZWZyZXNoIn0.wBnYbLB6kGinMRnM1ODqGmV1cv-VYMBzPZUNGsRDGqU",
"roles": ["admin"], // typically empty, right now this is only used for admins
"username":"jjcm"
}
POST /user/refresh-access-token
Refreshes the access token. Returns a new access token and a new refresh token.
Example payload
{
"refreshToken":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6ImpAampjbS5vcmciLCJleHBpcmVzQXQiOjE3NDQ2NzE2MjksInR5cGUiOiJyZWZyZXNoIn0.wBnYbLB6kGinMRnM1ODqGmV1cv-VYMBzPZUNGsRDGqU",
}
Example response
{
"accessToken":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6ImpAampjbS5vcmciLCJleHBpcmVzQXQiOjE3MDg5ODg2NzIsInR5cGUiOiJhY2Nlc3MifQ.m1vCcqE41C11us1WZnn2suxCMmRh5kcrzd200BaCips",
"refreshToken":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6ImpAampjbS5vcmciLCJleHBpcmVzQXQiOjE3NDQ2NzE4NzIsInR5cGUiOiJyZWZyZXNoIn0.D_NunlFZBMR73ryqlcKBzLZaZnGyP3LyzW6m0JQy0nM",
}
POST /user/register
Creates a new user. Returns the registered info along with an access token and a refresh token.
Example payload
{
"username": "jjcm",
"email": "jjcm@non.io",
"password": "hunter2",
}
Example response
{
"accessToken":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6ImFzZGZAYXNkZi5jb20iLCJleHBpcmVzQXQiOjE1ODMxNDc1NDh9.okbK22xZYZFk19K_NwLd7g48mxQZfWR5filMadonSe8",
"refreshToken":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6ImpAampjbS5vcmciLCJleHBpcmVzQXQiOjE3NDQ2NzE2MjksInR5cGUiOiJyZWZyZXNoIn0.wBnYbLB6kGinMRnM1ODqGmV1cv-VYMBzPZUNGsRDGqU",
"username":"jjcm"
}
GET /user/username-is-available/:username
Returns a boolean based on if the requested username is available
Requirements
None. Should be available publicly
Example response
true
Notifications API
Model
{
"id": Number,
"comment_id": Number,
"date": Number,
"post": String, //refers to the post's url
"post_title": String,
"post_type": String,
"content": String, //rich text in Quill format
"user": String,
"upvotes": Number,
"downvotes": Number,
"parent": Number,
"parent_content": String, //rich text in Quill format
"edited": Boolean,
"read": Boolean
}
GET /notifications
Should return 100 notifications, sorted by most recent.
Requirements
-
Authentication
With no auth, should return401 Unauthorized
Parameters
Returns only unread notifications if set to true
-
true
Only returns notifications that are unread.
-
false default
Returns all notifications.
Example response
{
"notifications": [
{
"id": 1,
"comment_id": 121100,
"date": 1691296535000,
"post": "nonio-changelog-9",
"post_title": "Nonio update - Notifications and guest contributions",
"post_type": "blog",
"content": "{\"ops\":[{\"insert\":\"Nice work!\\n\"}]}",
"user": "avocado",
"upvotes": 1,
"downvotes": 0,
"parent": 0,
"parent_content": "",
"edited": false,
"read": true
},
{
"id": 2,
"comment_id": 121101,
"date": 1691297044000,
"post": "avo-coffeeshop",
"post_title": "Avocado the dog",
"post_type": "image",
"content": "{\"ops\":[{\"insert\":\"Thank you Avo, very cool!\\n\"}]}",
"user": "kate",
"upvotes": 1,
"downvotes": 0,
"parent": 0,
"parent_content": "",
"edited": false,
"read": true
},
// ...etc
]
}
GET /notifications/unread-count
Gets the count of unread notifications for the user.
Requirements
-
Authentication
With no auth, should return401 Unauthorized
Example response
4
GET /notification/mark-read
Marks a specific notification ID as read.
Requirements
-
Authentication
With no auth, should return401 Unauthorized
Example payload
{
"id": 1
}
Example response
true