Skip to content

This repository contains AccelByte platform SDKs generated from OpenAPI specs.

License

Notifications You must be signed in to change notification settings

encyphered/accelbyte-python-sdk

 
 

Repository files navigation

AccelByte Python SDK

Installation

pip install requests pyyaml pyjwt
pip install git+https://github.com/AccelByte/accelbyte-python-sdk.git@main#egg=accelbyte_py_sdk

Usage

Initializing

You'll have to initialize the SDK using the initialize() function.

import accelbyte_py_sdk

accelbyte_py_sdk.initialize()

you could also pass in options like so:

import accelbyte_py_sdk

from accelbyte_py_sdk.core import MyConfigRepository

my_config_repository = MyConfigRepository(
    base_url=environ["AB_BASE_URL"],
    client_id=environ["AB_CLIENT_ID"],
    client_secret=environ["AB_CLIENT_SECRET"],
    namespace=environ["AB_NAMESPACE"],
)
options = {
    "config": my_config_repository
}
accelbyte_py_sdk.initialize(options)

# you could still set some of these options after initializing.
# ex. accelbyte_py_sdk.core.set_config_repository(my_config_repository)

Calling functions

All* functions follow the return value format of result, error.

from os import environ

import accelbyte_py_sdk
from accelbyte_py_sdk.services.auth import login, logout

if __name__ == "__main__":
    accelbyte_py_sdk.initialize()

    username = environ["AB_USERNAME"]
    password = environ["AB_PASSWORD"]

    _, error = login(username, password)
    assert error is None

    _, error = logout()
    assert error is None

here login(username, password) and logout() are wrapper functions.

import accelbyte_py_sdk
from accelbyte_py_sdk.api.iam import token_grant_v3

if __name__ == "__main__":
    accelbyte_py_sdk.initialize()

    token, error = token_grant_v3(
        grant_type="client_credentials"
    )
    assert error is not None

you could also write your own wrapper functions by using the generated models and operations in accelbyte_py_sdk.api.<service-name>.

Generated code

Models

Each definition in #/definitions/ is turned into a Model.

Example:

---
UserProfileInfo:
  type: object
  properties:
    userId:
      type: string
    namespace:
      type: string
    firstName:
      type: string
    lastName:
      type: string
    avatarSmallUrl:
      type: string
    avatarUrl:
      type: string
    avatarLargeUrl:
      type: string
    status:
      type: string
      enum:
      - ACTIVE
      - INACTIVE
    language:
      type: string
    timeZone:
      type: string
    dateOfBirth:
      type: string
      format: date
    customAttributes:
      type: object
      additionalProperties:
        type: object
    zipCode:
      type: string
# accelbyte_py_sdk/api/basic/models/user_profile_info.py

from __future__ import annotations
from typing import Any, Dict, List, Optional, Tuple, Union

from ....core import Model


class UserProfileInfo(Model):
    """User profile info

    Properties:
        user_id: (userId) OPTIONAL str

        namespace: (namespace) OPTIONAL str

        first_name: (firstName) OPTIONAL str

        last_name: (lastName) OPTIONAL str

        avatar_small_url: (avatarSmallUrl) OPTIONAL str

        avatar_url: (avatarUrl) OPTIONAL str

        avatar_large_url: (avatarLargeUrl) OPTIONAL str

        status: (status) OPTIONAL str

        language: (language) OPTIONAL str

        time_zone: (timeZone) OPTIONAL str

        date_of_birth: (dateOfBirth) OPTIONAL str

        custom_attributes: (customAttributes) OPTIONAL Dict[str, Any]

        zip_code: (zipCode) OPTIONAL str
    """

    # region fields

    user_id: str                                                                                   # OPTIONAL
    namespace: str                                                                                 # OPTIONAL
    first_name: str                                                                                # OPTIONAL
    last_name: str                                                                                 # OPTIONAL
    avatar_small_url: str                                                                          # OPTIONAL
    avatar_url: str                                                                                # OPTIONAL
    avatar_large_url: str                                                                          # OPTIONAL
    status: str                                                                                    # OPTIONAL
    language: str                                                                                  # OPTIONAL
    time_zone: str                                                                                 # OPTIONAL
    date_of_birth: str                                                                             # OPTIONAL
    custom_attributes: Dict[str, Any]                                                              # OPTIONAL
    zip_code: str                                                                                  # OPTIONAL

    # endregion fields

there are also a number of utility functions generated with each model that should help in the ease of use.

# accelbyte_py_sdk/api/basic/models/user_profile_info.py

def with_user_id(self, value: str) -> UserProfileInfo:
    self.user_id = value
    return self

# other with_x() methods too

def to_dict(self, include_empty: bool = False) -> dict:
    return  # ...

@classmethod
def create(
    cls,
    # ...,
) -> UserProfileInfo:
    return  # ...

@classmethod
def create_from_dict(cls, dict_: dict, include_empty: bool = False) -> UserProfileInfo:
    return  # ...

@staticmethod
def get_field_info() -> Dict[str, str]:
    return  # ...

Operations

Each path item in #/paths is turned into an Operation.

Example:

---
"/v1/public/namespaces/{namespace}/users/{userId}/profiles":
  get:
    tags:
    - UserProfile
    summary: Get user profile
    description: 'Get user profile.<br>Other detail info: <ul><li><i>Required permission</i>:
      resource=<b>"NAMESPACE:{namespace}:USER:{userId}:PROFILE"</b>, action=2 <b>(READ)</b></li><li><i>Action
      code</i>: 11403</li><li><i>Returns</i>: user profile</li></ul>'
    operationId: publicGetUserProfileInfo
    produces:
    - application/json
    parameters:
    - name: namespace
      in: path
      description: namespace, only accept alphabet and numeric
      required: true
      type: string
    - name: userId
      in: path
      description: user's id, should follow UUID version 4 without hyphen
      required: true
      type: string
    responses:
      '200':
        description: Successful operation
        schema:
          "$ref": "#/definitions/UserProfileInfo"
      '400':
        description: "<table><tr><td>errorCode</td><td>errorMessage</td></tr><tr><td>20002</td><td>validation
          error</td></tr></table>"
        schema:
          "$ref": "#/definitions/ValidationErrorEntity"
      '401':
        description: "<table><tr><td>errorCode</td><td>errorMessage</td></tr><tr><td>20001</td><td>unauthorized</td></tr></table>"
        schema:
          "$ref": "#/definitions/ErrorEntity"
      '403':
        description: "<table><tr><td>errorCode</td><td>errorMessage</td></tr><tr><td>20013</td><td>insufficient
          permission</td></tr></table>"
        schema:
          "$ref": "#/definitions/ErrorEntity"
      '404':
        description: "<table><tr><td>errorCode</td><td>errorMessage</td></tr><tr><td>11440</td><td>user
          profile not found</td></tr></table>"
        schema:
          "$ref": "#/definitions/ErrorEntity"
    security:
    - authorization: []
    x-authorization:
      resource: NAMESPACE:{namespace}:USER:{userId}:PROFILE
      action: '2'
# accelbyte_py_sdk/api/basic/operations/user_profile/get_user_profile_info.py

from __future__ import annotations
from typing import Any, Dict, List, Optional, Tuple, Union

from .....core import Operation
from .....core import HttpResponse

from ...models import ErrorEntity
from ...models import UserProfilePrivateInfo
from ...models import ValidationErrorEntity


class GetUserProfileInfo(Operation):
    """Get user profile (getUserProfileInfo)

    Properties:
        url: /basic/v1/admin/namespaces/{namespace}/users/{userId}/profiles

        method: GET

        tags: UserProfile

        consumes: []

        produces: ["application/json"]

        security: bearer

        namespace: (namespace) REQUIRED str in path

        user_id: (userId) REQUIRED str in path

    Responses:
        200: OK - UserProfilePrivateInfo (successful operation)

        400: Bad Request - ValidationErrorEntity (errorCode: 20002 | errorMessage: validation error)

        401: Unauthorized - ErrorEntity (errorCode: 20001 | errorMessage: unauthorized)

        403: Forbidden - ErrorEntity (errorCode: 20013 | errorMessage: insufficient permission)

        404: Not Found - ErrorEntity (errorCode: 11440 | errorMessage: user profile not found)
    """

    # region fields

    _url: str = "/basic/v1/admin/namespaces/{namespace}/users/{userId}/profiles"
    _method: str = "GET"
    _consumes: List[str] = []
    _produces: List[str] = ["application/json"]
    _security: Optional[str] = "bearer"
    _location_query: str = None

    namespace: str                                                                                 # REQUIRED in [path]
    user_id: str                                                                                   # REQUIRED in [path]

    # endregion fields

    # region properties

    @property
    def url(self) -> str:
        return self._url

    @property
    def method(self) -> str:
        return self._method

    @property
    def consumes(self) -> List[str]:
        return self._consumes

    @property
    def produces(self) -> List[str]:
        return self._produces

    @property
    def security(self) -> Optional[str]:
        return self._security

    @property
    def location_query(self) -> str:
        return self._location_query

    # endregion properties

same with the models there are also a number of utility functions generated with each operation that should help in the ease of use.

# accelbyte_py_sdk/api/basic/operations/user_profile/get_user_profile_info.py

def get_full_url(self, base_url: Union[None, str] = None) -> str:
    result = base_url if base_url is not None else ""

    # path params
    url = self.url
    for k, v in self.get_path_params().items():
        url = url.replace(f"{{{k}}}", v)
    result += url

    return result

# noinspection PyMethodMayBeStatic
def get_all_required_fields(self) -> List[str]:
    return [
        "namespace",
        "user_id",
    ]

def get_all_params(self) -> dict:
    return  # ...

def get_path_params(self) -> dict:
    return  # ...

# there would also be: get_body_params(), get_form_data_params(), get_header_params, get_query_params() too if the operation has those.

def is_valid(self) -> bool:
    if not hasattr(self, "namespace") or self.namespace is None:
        return False
    if not hasattr(self, "user_id") or self.user_id is None:
        return False
    return True

def with_namespace(self, value: str) -> GetUserProfileInfo:
    self.namespace = value
    return self

# other with_x() methods too

def to_dict(self, include_empty: bool = False) -> dict:
    return  # ...

# noinspection PyMethodMayBeStatic
def parse_response(self, code: int, content_type: str, content: Any) -> Tuple[Union[None, UserProfilePrivateInfo], Union[None, ErrorEntity, ValidationErrorEntity]]:
    """Parse the given response.

    200: OK - UserProfilePrivateInfo (successful operation)

    400: Bad Request - ValidationErrorEntity (errorCode: 20002 | errorMessage: validation error)

    401: Unauthorized - ErrorEntity (errorCode: 20001 | errorMessage: unauthorized)

    403: Forbidden - ErrorEntity (errorCode: 20013 | errorMessage: insufficient permission)

    404: Not Found - ErrorEntity (errorCode: 11440 | errorMessage: user profile not found)
    """
    if code == 200:
        return UserProfilePrivateInfo.create_from_dict(content), None
    if code == 400:
        return None, ValidationErrorEntity.create_from_dict(content)
    if code == 401:
        return None, ErrorEntity.create_from_dict(content)
    if code == 403:
        return None, ErrorEntity.create_from_dict(content)
    if code == 404:
        return None, ErrorEntity.create_from_dict(content)
    return None, HttpResponse.create_unhandled_error()

# the return value of parse_response follows the format Tuple[Union[None, all successful return codes], Union[None, all failure return codes]]

@classmethod
def create(
    cls,
    # ...,
) -> UserProfileInfo:
    return  # ...

@classmethod
def create_from_dict(cls, dict_: dict, include_empty: bool = False) -> UserProfileInfo:
    return  # ...

@staticmethod
def get_field_info() -> Dict[str, str]:
    return  # ...

Creating

💡 there are 4 ways to create an instance of these models and operations.

# 1. using the python __init__() function then setting the parameters manually:
model = ModelName()
model.param_a = "foo"
model.param_b = "bar"

# 2. using the python __init__() function together with the 'with_x' methods:
# # the 'with_x' functions are type annotated and will show warnings if a wrong type is passed.
model = ModelName() \
    .with_param_a("foo") \
    .with_param_b("bar")

# 3. using the ModelName.create(..) class method:
# # parameters here are also type annotated and will throw a TypeError if a required field was not filled out.
model = ModelName.create(
    param_a="foo",
    param_b="bar",
)

# 4. using the ModelName.create_from_dict(..) class method:
# # this method also has a 'include_empty' option that would get ignore values that evaluate to False, None, or len() == 0.
model_params = {
    "param_a": "foo",
    "param_b": "bar",
    "param_c": False,
    "param_d": None,
    "param_e": [],
    "param_f": {},
}
model = ModelName.create_from_dict(model_params)

# all of these apply to all operations too.

Wrappers

To improve ergonomics the code generator also generates wrappers around the operations. The purpose of these wrappers is to automatically fill up parameters that the SDK already knows. (e.g. namespace, client_id, access_token, etc.)

They are located at accelbyte_py_sdk.api.<service-name>.wrappers but can be accessed like so:

import accelbyte_py_sdk
from accelbyte_py_sdk.api.iam import token_grant_v3

if __name__ == "__main__":
    accelbyte_py_sdk.initialize()

    token, error = token_grant_v3(
        grant_type="client_credentials"
    )
    assert error is not None

The wrapper function token_grant_v3 is a wrapper for the TokenGrantV3 operation. It automatically passes in the information needed like the Basic Auth Headers. The values are gotten from the current ConfigRepository.

continuing from the previous examples, would be:

# accelbyte_py_sdk/api/basic/wrappers/_user_profile.py

from typing import Any, Dict, List, Optional, Tuple, Union

from ....core import get_namespace as get_services_namespace
from ....core import run_request
from ....core import same_doc_as

from ..operations.user_profile import GetUserProfileInfo


@same_doc_as(GetUserProfileInfo)
def get_user_profile_info(user_id: str, namespace: Optional[str] = None):
    if namespace is None:
        namespace, error = get_services_namespace()
        if error:
            return None, error
    request = GetUserProfileInfo.create(
        user_id=user_id,
        namespace=namespace,
    )
    return run_request(request)

this wrapper function automatically fills up the required path parameter namespace.

now to use it only the user_id is now required.

import accelbyte_py_sdk
from accelbyte_py_sdk.api.basic import get_user_profile_info

if __name__ == "__main__":
    accelbyte_py_sdk.initialize()

    user_profile_info, error = get_user_profile_info(user_id="lorem")
    assert error is not None

    print(f"Hello there {user_profile_info.first_name}!")

Sample App

The SDK also comes with a sample app.

To install follow these commands:

$ python -m venv venv-sample
$ source venv-sample/bin/activate
$ pip install -r requirements-sample.txt

$ python -m sample_app --help

The last command should output this:

Usage: python -m sample_app [OPTIONS] COMMAND [ARGS]...

Options:
  --help  Show this message and exit.

Commands:
  add-client-permissions
  add-role-managers
  add-role-members
  add-user-ban
  add-user-permissions
  add-user-role
  create-client
  create-role
  create-role-permission
  create-stat
  delete-client
  delete-client-permission
  delete-role
  delete-role-as-admin
  delete-role-managers
  delete-role-members
  delete-role-permission
  delete-role-permissions
  delete-stat
  delete-user
  delete-user-permission
  delete-user-permissions
  delete-user-role
  delete-user-roles
  get-ban-reasons
  get-ban-types
  get-ban-types-with-namespace
  get-banned-users
  get-clients-by-namespace
  get-clients-by-namespace-by-id
  get-my-admin-user
  get-my-public-user
  get-public-user-by-id
  get-role-by-id
  get-role-managers
  get-role-members
  get-search-user
  get-stat
  get-stats
  get-user-bans
  get-user-by-user-id
  get-user-roles
  get-users-by-email-addresses
  get-verification-code
  login
  login-client
  logout
  query-stats
  register-user
  send-verification-code
  set-role-as-admin
  update-client
  update-client-permissions
  update-role
  update-stat
  update-user
  update-user-ban
  update-user-permissions
  update-user-roles
  verify-account
  verify-code
  verify-user

You can get more information for each command by using this syntax:

$ python -m sample_app COMMAND --help

You will have to set first the following environment variables:

#Used by all operations
export AB_BASE_URL="https://env.accelbyte.io"

#Used by some operations
export AB_NAMESPACE="accelbyte"

#Used when logging in as client
export AB_CLIENT_ID="your-client-id"
export AB_CLIENT_SECRET="your-client-secret"

#Used when logging in as user
export AB_USERNAME="your-username"
export AB_PASSWORD="your-password"

Examples

Usage: python -m sample_app login [OPTIONS] USERNAME PASSWORD

Options:
  --doc BOOLEAN
  --help         Show this message and exit.

$ python -m sample_app login USERNAME PASSWORD

Login success.
access_token: ****
Usage: python -m sample_app login-client [OPTIONS]

Options:
  --doc BOOLEAN
  --help         Show this message and exit.

$ python -m sample_app login-client --doc true

OAuth2 access token generation endpoint (TokenGrantV3)

    Properties:
        url: /iam/v3/oauth/token

        method: POST

        tags: OAuth2.0

        consumes: ["application/x-www-form-urlencoded"]

        produces: ["application/json"]

        security: basic

        device_id: (device_id) OPTIONAL str in header

        grant_type: (grant_type) REQUIRED str in form_data

        code: (code) OPTIONAL str in form_data

        code_verifier: (code_verifier) OPTIONAL str in form_data

        client_id: (client_id) OPTIONAL str in form_data

        redirect_uri: (redirect_uri) OPTIONAL str in form_data

        refresh_token: (refresh_token) OPTIONAL str in form_data

    Responses:
        200: OK - OauthmodelTokenResponseV3 (Token returned)

        400: Bad Request - OauthmodelErrorResponse (InvalidRequest)

        401: Unauthorized - OauthmodelErrorResponse (Client authentication failed)

        403: Forbidden - OauthmodelErrorResponse (Unauthorized access)

Login success.
access_token: ****

Most commands will require you to login as either a client or as a user. For these commands you'll have to pass either --login_as client or --login_as user.

Usage: python -m sample_app get-ban-types [OPTIONS]

Options:
  --doc BOOLEAN
  --login_as [client|user]
  --help                    Show this message and exit.

$ python -m sample_app get-ban-types --login_as user

Get ban types success.
Ban Types: CHAT_SEND, CHAT_ALL, VOICE_SEND, VOICE_ALL, COMMUNITY, TRADE_INITIATE, TRADE_ALL, ORDER_AND_PAYMENT, MARKETPLACE_LIST, MARKETPLACE_ALL, LOGIN, STATISTICS, MATCHMAKING, UGC_CREATE_UPDATE
Usage: python -m sample_app register-user [OPTIONS] DISPLAY_NAME EMAIL_ADDRESS
                                          DATE_OF_BIRTH COUNTRY PASSWORD

Options:
  --namespace TEXT
  --role_id TEXT
  --doc BOOLEAN
  --login_as [client|user]
  --help            Show this message and exit.

$ python -m sample_app register-user eagerhamster6800 vi7xUuNc4j@fakemail.com 2000-09-23 US "****" --login_as client

User registration success.
authType: EMAILPASSWD
country: US
dateOfBirth: '2000-09-23T00:00:00Z'
displayName: eagerhamster6800
emailAddress: vi7xuunc4j@fakemail.com
namespace: ****
userId: ****
Usage: python -m sample_app get-my-admin-user [OPTIONS]

Options:
  --doc BOOLEAN
  --login_as [client|user]
  --help         Show this message and exit.

$ python -m sample_app get-my-admin-user --login_as user

Get my admin user success.
...
userId: ****
userName: ****
Usage: python -m sample_app update-client [OPTIONS] CLIENT_ID
                                          CLIENT_UPDATE_REQUEST

Options:
  --namespace TEXT
  --doc BOOLEAN
  --login_as [client|user]
  --help            Show this message and exit.

$ python -m sample_app update-client **** {"clientName": "****"} --login_as user

Update client success.
clientId: ****
clientName: ****
clientPermissions:
- action: 2
  resource: CLIENT
createdAt: '2020-09-23T00:00:00.000000Z'
modifiedAt: '2021-09-23T00:00:30.000000Z'
namespace: ****
oauthClientType: Confidential
redirectUri: http://127.0.0.1
scopes:
- account
Usage: python -m sample_app update-user [OPTIONS] USER_ID

Options:
  --country TEXT
  --date_of_birth TEXT
  --display_name TEXT
  --language_tag TEXT
  --user_name TEXT
  --namespace TEXT
  --doc BOOLEAN
  --login_as [client|user]
  --help                Show this message and exit.

$ python -m sample_app update-user **** --date_of_birth 2000-09-23 --login_as user

Update user success.
...
dateOfBirth: '2000-09-23T00:00:00Z'
lastDateOfBirthChangedTime: '2021-09-23T07:00:00.000000Z'

About

This repository contains AccelByte platform SDKs generated from OpenAPI specs.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Python 100.0%