Enable pagination on profile timeline
This commit is contained in:
parent
fc153a3156
commit
42624ab9a5
5 changed files with 54 additions and 9 deletions
|
@ -5,6 +5,35 @@ info:
|
||||||
version: 1.0.0
|
version: 1.0.0
|
||||||
|
|
||||||
paths:
|
paths:
|
||||||
|
/api/v1/accounts/{account_id}/statuses:
|
||||||
|
get:
|
||||||
|
summary: Statuses posted to the given account.
|
||||||
|
parameters:
|
||||||
|
- $ref: '#/components/parameters/account_id'
|
||||||
|
- name: max_id
|
||||||
|
in: query
|
||||||
|
description: Return results older than this ID.
|
||||||
|
required: false
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
format: uuid
|
||||||
|
- name: limit
|
||||||
|
in: query
|
||||||
|
description: Maximum number of results to return.
|
||||||
|
required: false
|
||||||
|
schema:
|
||||||
|
type: integer
|
||||||
|
default: 20
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
description: Successful operation
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
description: Post list
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: '#/components/schemas/Status'
|
||||||
/api/v1/statuses/{status_id}:
|
/api/v1/statuses/{status_id}:
|
||||||
delete:
|
delete:
|
||||||
summary: Delete post
|
summary: Delete post
|
||||||
|
@ -132,6 +161,14 @@ paths:
|
||||||
|
|
||||||
components:
|
components:
|
||||||
parameters:
|
parameters:
|
||||||
|
account_id:
|
||||||
|
name: account_id
|
||||||
|
in: path
|
||||||
|
description: Profile ID
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
format: uuid
|
||||||
status_id:
|
status_id:
|
||||||
name: status_id
|
name: status_id
|
||||||
in: path
|
in: path
|
||||||
|
|
|
@ -14,12 +14,13 @@ use crate::config::Config;
|
||||||
use crate::database::{Pool, get_database_client};
|
use crate::database::{Pool, get_database_client};
|
||||||
use crate::errors::{HttpError, ValidationError};
|
use crate::errors::{HttpError, ValidationError};
|
||||||
use crate::ethereum::gate::is_allowed_user;
|
use crate::ethereum::gate::is_allowed_user;
|
||||||
use crate::mastodon_api::statuses::types::Status;
|
|
||||||
use crate::mastodon_api::oauth::auth::get_current_user;
|
use crate::mastodon_api::oauth::auth::get_current_user;
|
||||||
use crate::models::posts::helpers::{
|
use crate::models::posts::helpers::{
|
||||||
get_actions_for_posts,
|
get_actions_for_posts,
|
||||||
get_reposted_posts,
|
get_reposted_posts,
|
||||||
};
|
};
|
||||||
|
use crate::mastodon_api::statuses::types::Status;
|
||||||
|
use crate::mastodon_api::timelines::types::TimelineQueryParams;
|
||||||
use crate::models::posts::queries::get_posts_by_author;
|
use crate::models::posts::queries::get_posts_by_author;
|
||||||
use crate::models::profiles::queries::{
|
use crate::models::profiles::queries::{
|
||||||
get_followers,
|
get_followers,
|
||||||
|
@ -257,6 +258,7 @@ async fn get_account_statuses(
|
||||||
config: web::Data<Config>,
|
config: web::Data<Config>,
|
||||||
db_pool: web::Data<Pool>,
|
db_pool: web::Data<Pool>,
|
||||||
web::Path(account_id): web::Path<Uuid>,
|
web::Path(account_id): web::Path<Uuid>,
|
||||||
|
query_params: web::Query<TimelineQueryParams>,
|
||||||
) -> Result<HttpResponse, HttpError> {
|
) -> Result<HttpResponse, HttpError> {
|
||||||
let db_client = &**get_database_client(&db_pool).await?;
|
let db_client = &**get_database_client(&db_pool).await?;
|
||||||
let maybe_current_user = match auth {
|
let maybe_current_user = match auth {
|
||||||
|
@ -268,6 +270,8 @@ async fn get_account_statuses(
|
||||||
&account_id,
|
&account_id,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
|
query_params.max_id,
|
||||||
|
query_params.limit,
|
||||||
).await?;
|
).await?;
|
||||||
get_reposted_posts(db_client, posts.iter_mut().collect()).await?;
|
get_reposted_posts(db_client, posts.iter_mut().collect()).await?;
|
||||||
if let Some(user) = maybe_current_user {
|
if let Some(user) = maybe_current_user {
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
mod types;
|
pub mod types;
|
||||||
pub mod views;
|
pub mod views;
|
||||||
|
|
|
@ -26,8 +26,8 @@ async fn home_timeline(
|
||||||
let mut posts = get_home_timeline(
|
let mut posts = get_home_timeline(
|
||||||
db_client,
|
db_client,
|
||||||
¤t_user.id,
|
¤t_user.id,
|
||||||
query_params.limit,
|
|
||||||
query_params.max_id,
|
query_params.max_id,
|
||||||
|
query_params.limit,
|
||||||
).await?;
|
).await?;
|
||||||
get_reposted_posts(db_client, posts.iter_mut().collect()).await?;
|
get_reposted_posts(db_client, posts.iter_mut().collect()).await?;
|
||||||
get_actions_for_posts(
|
get_actions_for_posts(
|
||||||
|
|
|
@ -208,8 +208,8 @@ pub const RELATED_TAGS: &str =
|
||||||
pub async fn get_home_timeline(
|
pub async fn get_home_timeline(
|
||||||
db_client: &impl GenericClient,
|
db_client: &impl GenericClient,
|
||||||
current_user_id: &Uuid,
|
current_user_id: &Uuid,
|
||||||
limit: i64,
|
|
||||||
max_post_id: Option<Uuid>,
|
max_post_id: Option<Uuid>,
|
||||||
|
limit: i64,
|
||||||
) -> Result<Vec<Post>, DatabaseError> {
|
) -> Result<Vec<Post>, DatabaseError> {
|
||||||
// Select posts from follows + own posts.
|
// Select posts from follows + own posts.
|
||||||
// Exclude direct messages where current user is not mentioned.
|
// Exclude direct messages where current user is not mentioned.
|
||||||
|
@ -237,9 +237,9 @@ pub async fn get_home_timeline(
|
||||||
WHERE post_id = post.id AND profile_id = $1
|
WHERE post_id = post.id AND profile_id = $1
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
AND ($3::uuid IS NULL OR post.id < $3)
|
AND ($2::uuid IS NULL OR post.id < $2)
|
||||||
ORDER BY post.id DESC
|
ORDER BY post.id DESC
|
||||||
LIMIT $2
|
LIMIT $3
|
||||||
",
|
",
|
||||||
related_attachments=RELATED_ATTACHMENTS,
|
related_attachments=RELATED_ATTACHMENTS,
|
||||||
related_mentions=RELATED_MENTIONS,
|
related_mentions=RELATED_MENTIONS,
|
||||||
|
@ -248,7 +248,7 @@ pub async fn get_home_timeline(
|
||||||
);
|
);
|
||||||
let rows = db_client.query(
|
let rows = db_client.query(
|
||||||
statement.as_str(),
|
statement.as_str(),
|
||||||
&[¤t_user_id, &limit, &max_post_id],
|
&[¤t_user_id, &max_post_id, &limit],
|
||||||
).await?;
|
).await?;
|
||||||
let posts: Vec<Post> = rows.iter()
|
let posts: Vec<Post> = rows.iter()
|
||||||
.map(Post::try_from)
|
.map(Post::try_from)
|
||||||
|
@ -290,8 +290,11 @@ pub async fn get_posts_by_author(
|
||||||
account_id: &Uuid,
|
account_id: &Uuid,
|
||||||
include_replies: bool,
|
include_replies: bool,
|
||||||
include_private: bool,
|
include_private: bool,
|
||||||
|
max_post_id: Option<Uuid>,
|
||||||
|
limit: i64,
|
||||||
) -> Result<Vec<Post>, DatabaseError> {
|
) -> Result<Vec<Post>, DatabaseError> {
|
||||||
let mut condition = "post.author_id = $1".to_string();
|
let mut condition = "post.author_id = $1
|
||||||
|
AND ($2::uuid IS NULL OR post.id < $2)".to_string();
|
||||||
if !include_replies {
|
if !include_replies {
|
||||||
condition.push_str(" AND post.in_reply_to_id IS NULL");
|
condition.push_str(" AND post.in_reply_to_id IS NULL");
|
||||||
};
|
};
|
||||||
|
@ -313,6 +316,7 @@ pub async fn get_posts_by_author(
|
||||||
JOIN actor_profile ON post.author_id = actor_profile.id
|
JOIN actor_profile ON post.author_id = actor_profile.id
|
||||||
WHERE {condition}
|
WHERE {condition}
|
||||||
ORDER BY post.created_at DESC
|
ORDER BY post.created_at DESC
|
||||||
|
LIMIT $3
|
||||||
",
|
",
|
||||||
related_attachments=RELATED_ATTACHMENTS,
|
related_attachments=RELATED_ATTACHMENTS,
|
||||||
related_mentions=RELATED_MENTIONS,
|
related_mentions=RELATED_MENTIONS,
|
||||||
|
@ -321,7 +325,7 @@ pub async fn get_posts_by_author(
|
||||||
);
|
);
|
||||||
let rows = db_client.query(
|
let rows = db_client.query(
|
||||||
statement.as_str(),
|
statement.as_str(),
|
||||||
&[&account_id],
|
&[&account_id, &max_post_id, &limit],
|
||||||
).await?;
|
).await?;
|
||||||
let posts: Vec<Post> = rows.iter()
|
let posts: Vec<Post> = rows.iter()
|
||||||
.map(Post::try_from)
|
.map(Post::try_from)
|
||||||
|
|
Loading…
Reference in a new issue