Allow calling follow/unfollow API methods multiple times
For compatibility with Mastodon.
This commit is contained in:
parent
d46165f397
commit
6d331f7669
3 changed files with 97 additions and 27 deletions
|
@ -204,6 +204,38 @@ paths:
|
||||||
$ref: '#/components/schemas/Account'
|
$ref: '#/components/schemas/Account'
|
||||||
404:
|
404:
|
||||||
description: Profile not found
|
description: Profile not found
|
||||||
|
/api/v1/accounts/{account_id}/follow:
|
||||||
|
post:
|
||||||
|
summary: Follow the given actor.
|
||||||
|
security:
|
||||||
|
- tokenAuth: []
|
||||||
|
parameters:
|
||||||
|
- $ref: '#/components/parameters/account_id'
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
description: Successfully followed, or actor was already followed
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/Relationship'
|
||||||
|
404:
|
||||||
|
description: Profile not found
|
||||||
|
/api/v1/accounts/{account_id}/unfollow:
|
||||||
|
post:
|
||||||
|
summary: Unfollow the given actor.
|
||||||
|
security:
|
||||||
|
- tokenAuth: []
|
||||||
|
parameters:
|
||||||
|
- $ref: '#/components/parameters/account_id'
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
description: Successfully unfollowed, or actor was already not followed
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/Relationship'
|
||||||
|
404:
|
||||||
|
description: Profile not found
|
||||||
/api/v1/statuses/{status_id}:
|
/api/v1/statuses/{status_id}:
|
||||||
delete:
|
delete:
|
||||||
summary: Delete post
|
summary: Delete post
|
||||||
|
@ -330,6 +362,10 @@ paths:
|
||||||
$ref: '#/components/schemas/Status'
|
$ref: '#/components/schemas/Status'
|
||||||
|
|
||||||
components:
|
components:
|
||||||
|
securitySchemes:
|
||||||
|
tokenAuth:
|
||||||
|
type: http
|
||||||
|
scheme: bearer
|
||||||
parameters:
|
parameters:
|
||||||
account_id:
|
account_id:
|
||||||
name: account_id
|
name: account_id
|
||||||
|
@ -367,6 +403,22 @@ components:
|
||||||
description: Ethereum wallet address.
|
description: Ethereum wallet address.
|
||||||
type: string
|
type: string
|
||||||
example: '0xd8da6bf...'
|
example: '0xd8da6bf...'
|
||||||
|
Relationship:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
id:
|
||||||
|
description: The account id.
|
||||||
|
type: string
|
||||||
|
format: uuid
|
||||||
|
following:
|
||||||
|
description: Are you following this user?
|
||||||
|
type: boolean
|
||||||
|
followed_by:
|
||||||
|
description: Are you followed by this user?
|
||||||
|
type: boolean
|
||||||
|
requested:
|
||||||
|
description: Do you have a pending follow request for this user?
|
||||||
|
type: boolean
|
||||||
Status:
|
Status:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
|
|
|
@ -12,7 +12,7 @@ use crate::activitypub::actor::Actor;
|
||||||
use crate::activitypub::deliverer::deliver_activity;
|
use crate::activitypub::deliverer::deliver_activity;
|
||||||
use crate::config::Config;
|
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::{DatabaseError, HttpError, ValidationError};
|
||||||
use crate::ethereum::gate::is_allowed_user;
|
use crate::ethereum::gate::is_allowed_user;
|
||||||
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::{
|
||||||
|
@ -209,16 +209,25 @@ async fn follow_account(
|
||||||
let target = get_profile_by_id(db_client, &account_id).await?;
|
let target = get_profile_by_id(db_client, &account_id).await?;
|
||||||
if let Some(remote_actor) = target.actor_json {
|
if let Some(remote_actor) = target.actor_json {
|
||||||
// Remote follow
|
// Remote follow
|
||||||
let request = create_follow_request(db_client, ¤t_user.id, &target.id).await?;
|
match create_follow_request(db_client, ¤t_user.id, &target.id).await {
|
||||||
let activity = create_activity_follow(
|
Ok(request) => {
|
||||||
&config.instance_url(),
|
let activity = create_activity_follow(
|
||||||
¤t_user.profile,
|
&config.instance_url(),
|
||||||
&request.id,
|
¤t_user.profile,
|
||||||
&remote_actor.id,
|
&request.id,
|
||||||
);
|
&remote_actor.id,
|
||||||
deliver_activity(&config, ¤t_user, activity, vec![remote_actor]);
|
);
|
||||||
|
deliver_activity(&config, ¤t_user, activity, vec![remote_actor]);
|
||||||
|
},
|
||||||
|
Err(DatabaseError::AlreadyExists(_)) => (), // already following
|
||||||
|
Err(other_error) => return Err(other_error.into()),
|
||||||
|
};
|
||||||
} else {
|
} else {
|
||||||
follow(db_client, ¤t_user.id, &target.id).await?;
|
match follow(db_client, ¤t_user.id, &target.id).await {
|
||||||
|
Ok(_) => (),
|
||||||
|
Err(DatabaseError::AlreadyExists(_)) => (), // already following
|
||||||
|
Err(other_error) => return Err(other_error.into()),
|
||||||
|
};
|
||||||
};
|
};
|
||||||
let relationship = get_relationship(
|
let relationship = get_relationship(
|
||||||
db_client,
|
db_client,
|
||||||
|
@ -240,26 +249,35 @@ async fn unfollow_account(
|
||||||
let target = get_profile_by_id(db_client, &account_id).await?;
|
let target = get_profile_by_id(db_client, &account_id).await?;
|
||||||
if let Some(remote_actor) = target.actor_json {
|
if let Some(remote_actor) = target.actor_json {
|
||||||
// Remote follow
|
// Remote follow
|
||||||
let follow_request = get_follow_request_by_path(
|
match get_follow_request_by_path(
|
||||||
db_client,
|
db_client,
|
||||||
¤t_user.id,
|
¤t_user.id,
|
||||||
&target.id,
|
&target.id,
|
||||||
).await?;
|
).await {
|
||||||
unfollow(
|
Ok(follow_request) => {
|
||||||
db_client,
|
unfollow(
|
||||||
¤t_user.id,
|
db_client,
|
||||||
&target.id,
|
¤t_user.id,
|
||||||
).await?;
|
&target.id,
|
||||||
// Federate
|
).await?;
|
||||||
let activity = create_activity_undo_follow(
|
// Federate
|
||||||
&config.instance_url(),
|
let activity = create_activity_undo_follow(
|
||||||
¤t_user.profile,
|
&config.instance_url(),
|
||||||
&follow_request.id,
|
¤t_user.profile,
|
||||||
&remote_actor.id,
|
&follow_request.id,
|
||||||
);
|
&remote_actor.id,
|
||||||
deliver_activity(&config, ¤t_user, activity, vec![remote_actor]);
|
);
|
||||||
|
deliver_activity(&config, ¤t_user, activity, vec![remote_actor]);
|
||||||
|
},
|
||||||
|
Err(DatabaseError::NotFound(_)) => (), // not following
|
||||||
|
Err(other_error) => return Err(other_error.into()),
|
||||||
|
};
|
||||||
} else {
|
} else {
|
||||||
unfollow(db_client, ¤t_user.id, &target.id).await?;
|
match unfollow(db_client, ¤t_user.id, &target.id).await {
|
||||||
|
Ok(_) => (),
|
||||||
|
Err(DatabaseError::NotFound(_)) => (), // not following
|
||||||
|
Err(other_error) => return Err(other_error.into()),
|
||||||
|
};
|
||||||
};
|
};
|
||||||
let relationship = get_relationship(
|
let relationship = get_relationship(
|
||||||
db_client,
|
db_client,
|
||||||
|
|
|
@ -161,7 +161,7 @@ pub async fn create_follow_request(
|
||||||
&request.target_id,
|
&request.target_id,
|
||||||
&request.request_status,
|
&request.request_status,
|
||||||
],
|
],
|
||||||
).await?;
|
).await.map_err(catch_unique_violation("follow request"))?;
|
||||||
Ok(request)
|
Ok(request)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue