React properly to 422: Validation Failed. Status has already been taken errors

This commit is contained in:
Daniel Schwarz 2022-12-13 12:45:07 -05:00 committed by Dan Schwarz
parent 4ef866dcbe
commit ecb9c75f2e
1 changed files with 28 additions and 9 deletions

View File

@ -4,7 +4,7 @@ import uuid
from urllib.parse import urlparse, urlencode, quote
from toot import http, CLIENT_NAME, CLIENT_WEBSITE
from toot.exceptions import AuthenticationError
from toot.exceptions import AuthenticationError, ApiError
from toot.utils import str_bool
SCOPES = 'read write follow'
@ -27,6 +27,23 @@ def _tag_action(app, user, tag_name, action):
return http.post(app, user, url).json()
def _status_toggle_action(app, user, status_id, action, data=None):
url = '/api/v1/statuses/{}/{}'.format(status_id, action)
try:
response = http.post(app, user, url, data=data).json()
except ApiError as e:
# For "toggle" operations, Mastodon returns unhelpful
# 422: "Validation failed:"
# responses when you try to bookmark a status already
# bookmarked, or favourite a status already favourited
# so we just swallow those errors here
if str(e).startswith("Validation failed:"):
return None # FIXME: return mock OK Response object?
else:
# not the error we expected; re-raise the exception
raise e
return response
def create_app(domain, scheme='https'):
url = '{}://{}/api/v1/apps'.format(scheme, domain)
@ -184,38 +201,40 @@ def delete_status(app, user, status_id):
def favourite(app, user, status_id):
return _status_action(app, user, status_id, 'favourite')
return _status_toggle_action(app, user, status_id, 'favourite')
def unfavourite(app, user, status_id):
return _status_action(app, user, status_id, 'unfavourite')
return _status_toggle_action(app, user, status_id, 'unfavourite')
def reblog(app, user, status_id, visibility="public"):
return _status_action(app, user, status_id, 'reblog', data={"visibility": visibility})
return _status_toggle_action(app, user, status_id, 'reblog', data={"visibility": visibility})
def unreblog(app, user, status_id):
return _status_action(app, user, status_id, 'unreblog')
return _status_toggle_action(app, user, status_id, 'unreblog')
def pin(app, user, status_id):
return _status_action(app, user, status_id, 'pin')
return _status_toggle_action(app, user, status_id, 'pin')
def unpin(app, user, status_id):
return _status_action(app, user, status_id, 'unpin')
return _status_toggle_action(app, user, status_id, 'unpin')
def bookmark(app, user, status_id):
return _status_action(app, user, status_id, 'bookmark')
return _status_toggle_action(app, user, status_id, 'bookmark')
def unbookmark(app, user, status_id):
return _status_action(app, user, status_id, 'unbookmark')
return _status_toggle_action(app, user, status_id, 'unbookmark')
def translate(app, user, status_id):
# don't use status_toggle_action for translate as this is
# not toggling anything server-side; it's a read only operation.
return _status_action(app, user, status_id, 'translate')