kopia lustrzana https://github.com/halcy/Mastodon.py
carefully move some things into files, test if readthedocs still builds
rodzic
99432f538e
commit
48f1d31c72
Plik diff jest za duży
Load Diff
|
@ -0,0 +1,105 @@
|
|||
from .defaults import _DEFAULT_SCOPES, _SCOPE_SETS
|
||||
from .error import MastodonIllegalArgumentError, MastodonAPIError
|
||||
from .utility import api_version
|
||||
|
||||
class Mastodon():
|
||||
@api_version("2.7.0", "2.7.0", "3.4.0")
|
||||
def create_account(self, username, password, email, agreement=False, reason=None, locale="en", scopes=_DEFAULT_SCOPES, to_file=None, return_detailed_error=False):
|
||||
"""
|
||||
Creates a new user account with the given username, password and email. "agreement"
|
||||
must be set to true (after showing the user the instance's user agreement and having
|
||||
them agree to it), "locale" specifies the language for the confirmation email as an
|
||||
ISO 639-1 (two letter) or, if a language does not have one, 639-3 (three letter) language
|
||||
code. `reason` can be used to specify why a user would like to join if approved-registrations
|
||||
mode is on.
|
||||
|
||||
Does not require an access token, but does require a client grant.
|
||||
|
||||
By default, this method is rate-limited by IP to 5 requests per 30 minutes.
|
||||
|
||||
Returns an access token (just like log_in), which it can also persist to to_file,
|
||||
and sets it internally so that the user is now logged in. Note that this token
|
||||
can only be used after the user has confirmed their email.
|
||||
|
||||
By default, the function will throw if the account could not be created. Alternately,
|
||||
when `return_detailed_error` is passed, Mastodon.py will return the detailed error
|
||||
response that the API provides (Starting from version 3.4.0 - not checked here) as an dict with
|
||||
error details as the second return value and the token returned as `None` in case of error.
|
||||
The dict will contain a text `error` values as well as a `details` value which is a dict with
|
||||
one optional key for each potential field (`username`, `password`, `email` and `agreement`),
|
||||
each if present containing a dict with an `error` category and free text `description`.
|
||||
Valid error categories are:
|
||||
|
||||
* ERR_BLOCKED - When e-mail provider is not allowed
|
||||
* ERR_UNREACHABLE - When e-mail address does not resolve to any IP via DNS (MX, A, AAAA)
|
||||
* ERR_TAKEN - When username or e-mail are already taken
|
||||
* ERR_RESERVED - When a username is reserved, e.g. "webmaster" or "admin"
|
||||
* ERR_ACCEPTED - When agreement has not been accepted
|
||||
* ERR_BLANK - When a required attribute is blank
|
||||
* ERR_INVALID - When an attribute is malformed, e.g. wrong characters or invalid e-mail address
|
||||
* ERR_TOO_LONG - When an attribute is over the character limit
|
||||
* ERR_TOO_SHORT - When an attribute is under the character requirement
|
||||
* ERR_INCLUSION - When an attribute is not one of the allowed values, e.g. unsupported locale
|
||||
"""
|
||||
params = self.__generate_params(locals(), ['to_file', 'scopes'])
|
||||
params['client_id'] = self.client_id
|
||||
params['client_secret'] = self.client_secret
|
||||
|
||||
if not agreement:
|
||||
del params['agreement']
|
||||
|
||||
# Step 1: Get a user-free token via oauth
|
||||
try:
|
||||
oauth_params = {}
|
||||
oauth_params['scope'] = " ".join(scopes)
|
||||
oauth_params['client_id'] = self.client_id
|
||||
oauth_params['client_secret'] = self.client_secret
|
||||
oauth_params['grant_type'] = 'client_credentials'
|
||||
|
||||
response = self.__api_request('POST', '/oauth/token', oauth_params, do_ratelimiting=False)
|
||||
temp_access_token = response['access_token']
|
||||
except Exception as e:
|
||||
raise MastodonIllegalArgumentError('Invalid request during oauth phase: %s' % e)
|
||||
|
||||
# Step 2: Use that to create a user
|
||||
try:
|
||||
response = self.__api_request('POST', '/api/v1/accounts', params, do_ratelimiting=False, access_token_override=temp_access_token, skip_error_check=True)
|
||||
if "error" in response:
|
||||
if return_detailed_error:
|
||||
return None, response
|
||||
raise MastodonIllegalArgumentError('Invalid request: %s' % e)
|
||||
self.access_token = response['access_token']
|
||||
self.__set_refresh_token(response.get('refresh_token'))
|
||||
self.__set_token_expired(int(response.get('expires_in', 0)))
|
||||
except Exception as e:
|
||||
raise MastodonIllegalArgumentError('Invalid request')
|
||||
|
||||
# Step 3: Check scopes, persist, et cetera
|
||||
received_scopes = response["scope"].split(" ")
|
||||
for scope_set in _SCOPE_SETS.keys():
|
||||
if scope_set in received_scopes:
|
||||
received_scopes += _SCOPE_SETS[scope_set]
|
||||
|
||||
if not set(scopes) <= set(received_scopes):
|
||||
raise MastodonAPIError('Granted scopes "' + " ".join(received_scopes) + '" do not contain all of the requested scopes "' + " ".join(scopes) + '".')
|
||||
|
||||
if to_file is not None:
|
||||
with open(to_file, 'w') as token_file:
|
||||
token_file.write(response['access_token'] + "\n")
|
||||
token_file.write(self.api_base_url + "\n")
|
||||
|
||||
self.__logged_in_id = None
|
||||
|
||||
if return_detailed_error:
|
||||
return response['access_token'], {}
|
||||
else:
|
||||
return response['access_token']
|
||||
|
||||
@api_version("3.4.0", "3.4.0", "3.4.0")
|
||||
def email_resend_confirmation(self):
|
||||
"""
|
||||
Requests a re-send of the users confirmation mail for an unconfirmed logged in user.
|
||||
|
||||
Only available to the app that the user originally signed up with.
|
||||
"""
|
||||
self.__api_request('POST', '/api/v1/emails/confirmations')
|
|
@ -656,3 +656,14 @@ class Mastodon():
|
|||
elif base_url.startswith("https://") or base_url.startswith("onion://"):
|
||||
base_url = base_url[8:]
|
||||
return base_url
|
||||
|
||||
def __normalize_version_string(self, version_string):
|
||||
# Split off everything after the first space, to take care of Pleromalikes so that the parser doesn't get confused in case those have a + somewhere in their version
|
||||
version_string = version_string.split(" ")[0]
|
||||
try:
|
||||
# Attempt to split at + and check if the part after parses as a version string, to account for hometown
|
||||
parse_version_string(version_string.split("+")[1])
|
||||
return version_string.split("+")[1]
|
||||
except:
|
||||
# If this fails, assume that if there is a +, what is before that is the masto version (or that there is no +)
|
||||
return version_string.split("+")[0]
|
|
@ -0,0 +1,40 @@
|
|||
|
||||
# versions.py - versioning of return values
|
||||
|
||||
from .utility import max_version
|
||||
|
||||
# Dict versions
|
||||
_DICT_VERSION_APPLICATION = "2.7.2"
|
||||
_DICT_VERSION_MENTION = "1.0.0"
|
||||
_DICT_VERSION_MEDIA = "3.2.0"
|
||||
_DICT_VERSION_ACCOUNT = "3.3.0"
|
||||
_DICT_VERSION_POLL = "2.8.0"
|
||||
_DICT_VERSION_STATUS = max_version("3.1.0", _DICT_VERSION_MEDIA, _DICT_VERSION_ACCOUNT, _DICT_VERSION_APPLICATION, _DICT_VERSION_MENTION, _DICT_VERSION_POLL)
|
||||
_DICT_VERSION_INSTANCE = max_version("3.4.0", _DICT_VERSION_ACCOUNT)
|
||||
_DICT_VERSION_HASHTAG = "2.3.4"
|
||||
_DICT_VERSION_EMOJI = "3.0.0"
|
||||
_DICT_VERSION_RELATIONSHIP = "3.3.0"
|
||||
_DICT_VERSION_NOTIFICATION = max_version("3.5.0", _DICT_VERSION_ACCOUNT, _DICT_VERSION_STATUS)
|
||||
_DICT_VERSION_CONTEXT = max_version("1.0.0", _DICT_VERSION_STATUS)
|
||||
_DICT_VERSION_LIST = "2.1.0"
|
||||
_DICT_VERSION_CARD = "3.2.0"
|
||||
_DICT_VERSION_SEARCHRESULT = max_version("1.0.0", _DICT_VERSION_ACCOUNT, _DICT_VERSION_STATUS, _DICT_VERSION_HASHTAG)
|
||||
_DICT_VERSION_ACTIVITY = "2.1.2"
|
||||
_DICT_VERSION_REPORT = "2.9.1"
|
||||
_DICT_VERSION_PUSH = "2.4.0"
|
||||
_DICT_VERSION_PUSH_NOTIF = "2.4.0"
|
||||
_DICT_VERSION_FILTER = "2.4.3"
|
||||
_DICT_VERSION_CONVERSATION = max_version("2.6.0", _DICT_VERSION_ACCOUNT, _DICT_VERSION_STATUS)
|
||||
_DICT_VERSION_SCHEDULED_STATUS = max_version("2.7.0", _DICT_VERSION_STATUS)
|
||||
_DICT_VERSION_PREFERENCES = "2.8.0"
|
||||
_DICT_VERSION_ADMIN_ACCOUNT = max_version("4.0.0", _DICT_VERSION_ACCOUNT)
|
||||
_DICT_VERSION_FEATURED_TAG = "3.0.0"
|
||||
_DICT_VERSION_MARKER = "3.0.0"
|
||||
_DICT_VERSION_REACTION = "3.1.0"
|
||||
_DICT_VERSION_ANNOUNCEMENT = max_version("3.1.0", _DICT_VERSION_REACTION)
|
||||
_DICT_VERSION_STATUS_EDIT = "3.5.0"
|
||||
_DICT_VERSION_FAMILIAR_FOLLOWERS = max_version("3.5.0", _DICT_VERSION_ACCOUNT)
|
||||
_DICT_VERSION_ADMIN_DOMAIN_BLOCK = "4.0.0"
|
||||
_DICT_VERSION_ADMIN_MEASURE = "3.5.0"
|
||||
_DICT_VERSION_ADMIN_DIMENSION = "3.5.0"
|
||||
_DICT_VERSION_ADMIN_RETENTION = "3.5.0"
|
Ładowanie…
Reference in New Issue