Skip to main content

This is a simple library for working with the gmfy api.

Project description

ruff pypi version Number of tests



Our project is Python library that allows easy integration with gmfy API. With this SDK, you can conveniently manage mechanics that allow you to adjust user behavior, but also measure the effectiveness of such correction.

How it works 🎮

GMFY receives events related to user actions in the gamified system. This allows you to analyze user behavior before and after the introduction of gamification.

Through the administrative interface, various game mechanics are configured, taking into account incoming events. This is how ratings and leaderboards are built, user achievements are calculated and corporate currencies are awarded.

In order to give users feedback, you need to visualize your achievements. This could be a block in an existing user profile, contextual widgets, or a separate page with achievement results, available to users authorized in the gamified system.

Installation Guide ⤵️

To install the library, you need to choose how you want to use it: synchronously, asynchronously, or both. This approach ensures that you only install the necessary dependencies, keeping your project clean and efficient. Depending on your use case, you can select the appropriate mode as follows:

  • Use synchronously:
pip install 'gmfy[sync]'
  • Use asynchronously:
pip install 'gmfy[async]'
  • Use both synchronously and asynchronously:
pip install 'gmfy[sync,async]'

By selecting the appropriate mode, you ensure that your project includes only the dependencies it needs, avoiding unnecessary clutter.

Quick Start ⭐

The first thing you need to do is initialize the SDK to interact with GMFY

Import a synchronous or asynchronous class to initialize your data. As an example, we will consider both options

from gmfy.sync_clients.gmfy_client import GMFYClientSync
from gmfy.async_clients.gmfy_client import GMFYClientAsync

### Synchronous use ###
gmfy_sync = GMFYClientSync(GMFY_API_KEY, GMFY_URL)

### Asynchronous use ###
gmfy_async = GMFYClientAsync(GMFY_API_KEY, GMFY_URL)

❗Replace GMFY_API_KEY and GMFY_URL with your actual credentials.❗

If you want to change such parameters as request verification or request timeout, you can specify these parameters additionally:

from gmfy.sync_clients.gmfy_client import GMFYClientSync
from gmfy.async_clients.gmfy_client import GMFYClientAsync


### Synchronous use ###
gmfy_sync = GMFYClientSync(GMFY_API_KEY, GMFY_URL, verify=True, timeout=120)

### Asynchronous use ###
gmfy_async = GMFYClientAsync(GMFY_API_KEY, GMFY_URL, verify=True, timeout=120)

POST methods ➡️

1️⃣ Create events to GMFY

1. Define Event Types and Actions

Create custom classes inheriting from BaseEventType and BaseEventAction. For example:

from gmfy import BaseEventAction, BaseEventType


class EventType(BaseEventType):
    subscription = "subscription"
    register = "register"
    visit_user = "visit_user"


class EventAction(BaseEventAction):
    create = "create"
    remove = "remove"
  • EventType must inherit from BaseEventType
  • EventAction must inherit from BaseEventAction

You can also expand these classes with your own functionality, for example likes or dislikes.

This needs to be done so that you can add your types and actions.

❕You can use both the list of events and single events. To begin with, we will analyze the use of sending several events ❕

2. Create your events

Now you need to create your own events. They can be classically, actionable, or have an idempotency key. Depending on what type of event you need, inherit from a specific class:

  • Classic Event

It can be an ordinary event, for example, user registration on the site:

from gmfy import BaseEvent
from typing import Literal
from pydantic import Field


class RegisterEvent(BaseEvent):
    event_type: Literal[EventType.register] = Field(exclude=True)
  • Action Event

This event is needed for actions that can be created and removed. For example, likes, subscriptions, and so on:

from gmfy import BaseActionEvent
from typing import Literal
from pydantic import Field


class SubscriptionEvent(BaseActionEvent):
    event_type: Literal[EventType.subscription] = Field(exclude=True)
  • Unique Event

This event is needed to identify the action. For example, viewing specific content:

from gmfy import BaseUniqueEvent
from typing import Literal
from pydantic import Field


class VisitUserEvent(BaseUniqueEvent):
    event_type: Literal[EventType.visit_user] = Field(exclude=True)

Important: If you skip this step, you will get a TypeError error:

TypeError: Event classes inherited from BaseEvent were not found in your project. Ensure you've created your events by inheriting from BaseEvents.

To resolve this issue, ensure that your events are properly set up by inheriting from BaseEvents. Create a Python package and include a file where you initialize your classes that extend BaseEvents. This step is essential for smooth operation.

3. Prepare data for send events

To send data, you can use class EventData to work with objects:

from gmfy.data import EventData

create_subscription_event = EventData(
        event_type=EventType.subscription,
        user_id=f"{user_id}",
        event_action=EventAction.create
    ).model_dump(by_alias=True)

register_event = EventData(
        event_type=EventType.register,
        user_id=f"{user_id}",
    ).model_dump(by_alias=True)

visit_user_event = EventData(
        event_type=EventType.visit_user,
        user_id=f"{user_id}",
        idempotence_key=f"{instance.id}",
    ).model_dump(by_alias=True)

event_data = [create_subscription_event, register_event, visit_user_event]

Or you can use a dictionary structure to provide the data to be sent

event_data = [
    {
        "event_type": EventType.subscription,
        "user_id": f"{user.id}",
        "event_action": EventAction.create,
    },
    {
        "event_type": EventType.register,
        "user_id": f"{user.id}",
    },
    {
        "event_type": EventType.visit_user,
        "user_id": f"{user.id}",
        "idempotence_key": f"{instance.id}",
    },
]

4. Send events

Now that you have prepared the data for sending, you can send a request to GMFY and create an event.

To do this, call the create_batch_events method regardless of what type of synchronization you have chosen

### Synchronous use ###
gmfy_sync.create_batch_events(event_data)

### Asynchronous use ###
await gmfy_async.create_batch_events(event_data)

Well, now let's figure out how you can send not just a list of events, but single events

The basic logic for preparing the data and sending the request does not change. The only important thing is that now you need to work with dict instead of list. Let's see the differences from these options:

1. Prepare data for send single event

from gmfy import EventData

event_data = EventData(
    event_type=EventType.subscription,
    user_id=f"{user_id}",
    event_action=EventAction.create
).model_dump(by_alias=True)

Well, according to tradition, if you want to work directly with dictionaries, then do this:

event_data = {
    "event_type": EventType.subscription,
    "user_id": f"{user.id}",
    "event_action": EventAction.create,
},

2. Create your event

from gmfy import BaseActionEvent
from typing import Literal
from pydantic import Field


class SubscriptionEvent(BaseActionEvent):
    event_type: Literal[EventType.subscription] = Field(exclude=True)

3. Send single event

Now we can send a request to create one event. To do this, use the create_event method as follows:

### Synchronous use ###
gmfy_sync.create_event(event_data)

### Asynchronous use ###
await gmfy_async.create_event(event_data)

2️⃣ Create payments to GMFY

To send a post request to send a payment to GMFY, follow these steps:

1. Prepare data for send payment

Similar to the previous example, you can use a class or create your own data dictionary. Both options are presented below:

  • Using the class PaymentData:
from gmfy import PaymentData, LocaleEnum

payment_data = PaymentData(
    amount={"value": 100, "currency": "USD"},
    confirmation={"returnUrl": "https://example.com/"},
    user_id=f"{user_id}",
    description="Payment for order #123",
    locale=LocaleEnum.EN,
).model_dump(by_alias=True)
  • Using dictionary:
from gmfy import LocaleEnum

payment_data = {
    "amount": {"value": 100, "currency": "USD"},
    "confirmation": {"returnUrl": "https://example.com/"},
    "user_id": f"{user_id}",
    "description": "Payment for order #123",
    "locale": LocaleEnum.EN,
}

2. Use basic ones or create your own classes for data management

To validate data, you can use the base classes BasePayment, BaseAmount and BaseConfirmation or override them if you have such a need:

  • Use base classes:
from gmfy import BasePayment

payment = BasePayment(**payment_data)
  • Create your own classes:
from pydantic import Field

from gmfy import BasePayment, BaseAmount, BaseConfirmation


class CustomAmount(BaseAmount): ...
# modify the class according to your needs


class CustomConfirmation(BaseConfirmation): ...
# modify the class according to your needs


class CustomPayment(BasePayment):
    amount: CustomAmount = Field(...)
    confirmation: CustomConfirmation = Field(...)
    # modify the class according to your needs

3. Use the create_payment method to send a request to GMFY:

  • If you used a base class:
### Synchronous use ###
gmfy_sync.create_payment(BasePayment(**payment_data))

### Asynchronous use ###
await gmfy_async.create_payment(BasePayment(**payment_data))
  • If you created your own class:
### Synchronous use ###
gmfy_sync.create_payment(CustomPayment(**payment_data))

### Asynchronous use ###
await gmfy_async.create_payment(CustomPayment(**payment_data))

_Unlike creating an event, when creating a payment you will receive a response statusof 200, not 201, as

well as a response from the server:_

{
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "clientId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "status": "CREATED",
  "confirmationUrl": "string"
}

3️⃣ Create resend code to GMFY

You can also create a resend code by passing the payment id like this:

### Synchronous use ###
gmfy_sync.create_resend_code(payment_id=f"{payment_id}")

### Asynchronous use ###
await gmfy_async.create_resend_code(payment_id=f"{payment_id}")

It is important to note that you will receive a 200 OK status in response, as well as the following response:

{
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "clientId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "value": 0,
  "returnUrl": "string",
  "description": "string",
  "currency": "string",
  "status": "CREATED",
  "locale": "RU",
  "expiresIn": 0
}

GET methods ⬅️

1️⃣ Get user's data from GMFY

You can get information about all users or information about one user by ID using the get_users method

  1. Get a list of all users information:
### Synchronous use ###
gmfy_sync.get_users()

### Asynchronous use ###
await gmfy_async.get_users()
  1. Get information about one user by id
### Synchronous use ###
gmfy_sync.get_users(user_id=f"{user_id}")

### Asynchronous use ###
await gmfy_async.get_users(user_id=f"{user_id}")

*️⃣ Example response:

[
  {
    "userId": "string",
    "clientId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "userRatings": [
      {
        "userId": "string",
        "clientId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
        "ratingId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
        "name": "string",
        "value": 0,
        "metaInfo": {
          "additionalProp1": "string",
          "additionalProp2": "string",
          "additionalProp3": "string"
        },
        "position": 0
      }
    ],
    "userChallenges": [
      {
        "userId": "string",
        "challengeId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
        "clientId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
        "progress": 0,
        "passedSteps": [
          {
            "challengeStepId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
            "order": 0,
            "weight": 0,
            "dateComplete": "2024-08-19T13:03:31.653Z"
          }
        ],
        "metaInfo": {
          "additionalProp1": "string",
          "additionalProp2": "string",
          "additionalProp3": "string"
        },
        "name": "string"
      }
    ],
    "userBadges": [
      {
        "userId": "string",
        "badgeId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
        "clientId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
        "acquisitionDate": "2024-08-19T13:03:31.653Z",
        "metaInfo": {
          "additionalProp1": "string",
          "additionalProp2": "string",
          "additionalProp3": "string"
        },
        "name": "string",
        "description": "string",
        "permanent": true,
        "count": 0
      }
    ],
    "userFeatures": [
      {
        "userId": "string",
        "featureId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
        "clientId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
        "accessDate": "2024-08-19T13:03:31.653Z",
        "metaInfo": {
          "additionalProp1": "string",
          "additionalProp2": "string",
          "additionalProp3": "string"
        },
        "name": "string",
        "description": "string"
      }
    ],
    "userAccountBalances": [
      {
        "userId": "string",
        "clientId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
        "resourceKey": "string",
        "amount": 0
      }
    ]
  }
]

2️⃣ Get user badges by user id

To get a list of user badges, use the get_user_badges method, passing it the user id:

### Synchronous use ###
gmfy_sync.get_user_badges(user_id=f"{user_id}")

### Asynchronous use ###
await gmfy_async.get_user_badges(user_id=f"{user_id}")

*️⃣ Example response:

[
  {
    "userId": "string",
    "badgeId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "clientId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "acquisitionDate": "2024-08-19T14:34:11.608Z",
    "metaInfo": {
      "additionalProp1": "string",
      "additionalProp2": "string",
      "additionalProp3": "string"
    },
    "name": "string",
    "description": "string",
    "permanent": true,
    "count": 0
  }
]

3️⃣ Get top of users in rating

Also you can get top of users in rating by id:

### Synchronous use ###
gmfy_sync.get_rating_top_users(rating_id=f"{rating_id})

### Asynchronous use ###
await gmfy_async.get_rating_top_users(rating_id=f"{rating_id}")

❗By default request has parameters offset = 0, limit = 10, sorted by ASC. But if you want to override them, you can do it like this:

### Synchronous use ###
gmfy_sync.get_rating_top_users(
    rating_id=f"{rating_id}",
    offset=5,
    limit=20,
    sort="DESC"
)

### Asynchronous use ###
gmfy_async.get_rating_top_users(
    rating_id=f"{rating_id}",
    offset=5,
    limit=20,
    sort="DESC"
)

*️⃣ Example response:

[
  {
    "userId": "string",
    "clientId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "ratingId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "name": "string",
    "value": 0,
    "metaInfo": {
      "additionalProp1": "string",
      "additionalProp2": "string",
      "additionalProp3": "string"
    },
    "position": 0
  }
]

4️⃣ Get top of users in challenge

You can get top of users in challenge by id:

### Synchronous use ###
gmfy_sync.get_challenge_top_users(challenge_id=f"{challenge_id}")

### Asynchronous use ###
await gmfy_async.get_challenge_top_users(challenge_id=f"{challenge_id}")

❗By default request has parameter limit = 10. But if you want to override them, you can do it like this:

### Synchronous use ###
gmfy_sync.get_challenge_top_users(challenge_id=f"{challenge_id}", limit=20)

### Asynchronous use ###
await gmfy_async.get_challenge_top_users(challenge_id=f"{challenge_id}", limit=20)

*️⃣ Example response:

[
  {
    "userId": "string",
    "challengeId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "clientId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "progress": 0,
    "passedSteps": [
      {
        "challengeStepId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
        "order": 0,
        "weight": 0,
        "dateComplete": "2024-08-19T14:20:26.219Z"
      }
    ],
    "metaInfo": {
      "additionalProp1": "string",
      "additionalProp2": "string",
      "additionalProp3": "string"
    },
    "name": "string"
  }
]

5️⃣ Get information about payment by id

Using the get_payment method you can get payment information like this

### Synchronous use ###
gmfy_sync.get_payment(payment_id=f"{payment_id}")

### Asynchronous use ###
await gmfy_async.get_payment(payment_id=f"{payment_id}")
  • *️⃣ Example response:
{
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "clientId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "value": 0,
  "returnUrl": "string",
  "description": "string",
  "currency": "string",
  "status": "CREATED",
  "locale": "RU",
  "expiresIn": 0
}

6️⃣ Get notification's information

You can receive notifications using the get_notifications method like this:

### Synchronous use ###
gmfy_sync.get_notifications()

### Asynchronous use ###
await gmfy_async.get_notifications()
  • *️⃣ Example response:
[
  {
    "userId": "string",
    "clientId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "message": "string"
  }
]

7️⃣ Get unread notification's information:

You can also get information about unread notifications of all users, or for a single user, if you specify his id. This can be done using the get_unread_notifications() method:

  • Get unread notifications for all users:
### Synchronous use ###
gmfy_sync.get_unread_notifications()

### Asynchronous use ###
await gmfy_async.get_unread_notifications()
  • Get unread notifications for single user by id:
### Synchronous use ###
gmfy_sync.get_unread_notifications(user_id=f"{user_id}")

### Asynchronous use ###
await gmfy_async.get_unread_notifications(user_id=f"{user_id}")
  • *️⃣ Example response for both options:
[
  {
    "userId": "string",
    "clientId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "message": "string"
  }
]

8️⃣ Get version of API GMFY

And, of course, you can get the API version using previously initialized classes using the get_api_version method

### Synchronous use ###
gmfy_sync.get_api_version()

### Asynchronous use ###
await gmfy_async.get_api_version()

*️⃣ Example response:

{
  "version": "1.0",
  "deploymentDate": "2024-07-22T17:28:03.876Z"
}

Contributors and Contact 💬

The GMFY SDK library were developed by Evgeny Izvekov and Yuriy Belotserkovskiy, and is actively maintained by our team. If you have any questions, suggestions, or feedback, feel free to reach out to us.

Happy gamifying! 👾

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

gmfy-0.0.4.tar.gz (17.9 kB view details)

Uploaded Source

Built Distribution

gmfy-0.0.4-py3-none-any.whl (16.2 kB view details)

Uploaded Python 3

File details

Details for the file gmfy-0.0.4.tar.gz.

File metadata

  • Download URL: gmfy-0.0.4.tar.gz
  • Upload date:
  • Size: 17.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.8.3 CPython/3.12.5 Linux/6.8.0-40-generic

File hashes

Hashes for gmfy-0.0.4.tar.gz
Algorithm Hash digest
SHA256 e2478ac3499154be46ddf03425250c68cd0094f08d14251eef61829df9406a1a
MD5 472fc739f583ab3bdef213473042f63f
BLAKE2b-256 a2337315822d421b26439b02ae4e28a3206f03bd37b97adb2d7f2249a9a68166

See more details on using hashes here.

File details

Details for the file gmfy-0.0.4-py3-none-any.whl.

File metadata

  • Download URL: gmfy-0.0.4-py3-none-any.whl
  • Upload date:
  • Size: 16.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.8.3 CPython/3.12.5 Linux/6.8.0-40-generic

File hashes

Hashes for gmfy-0.0.4-py3-none-any.whl
Algorithm Hash digest
SHA256 a49a66d7ce91164d746e79770e8c44f81dce3edb5e50ea4fe850e073f12b0d9e
MD5 ecc206f652c1820071bf10dce4b7d21e
BLAKE2b-256 3cc055445430428f309dc0562936a7494614ff9331754373185a3fa46ffa511b

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page