Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
22 changes: 22 additions & 0 deletions .cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,38 +11,60 @@
"misc"
],
"words": [
"AUTORESPONSE",
"AYΣTHPO",
"AΘHNAIΩN",
"AΠOΦAΣH",
"BIREYSEL",
"CLEARSKY",
"EINAI",
"EKKΛHΣIAΣ",
"EMΠAPΓKO",
"ENROUTE",
"EΠIBAΛEI",
"GIIN",
"ICEX",
"KAΘOΛIKO",
"Kilic",
"Lozina",
"Luka",
"MEΓAPIKO",
"MMSADVANCEDMESSAGESEGMENT",
"MMSWEBHOOKINBOUNDMESSAGESEGMENT",
"PSTN",
"SEHK",
"SMIL",
"SMPP",
"SZSE",
"Smil",
"Smpp",
"Snyk",
"TACIR",
"TENDLC",
"TWSE",
"USSD",
"WABA",
"aabe",
"aenum",
"conint",
"conlist",
"defaultplaceholders",
"dtmf",
"formdata",
"httpx",
"ibsso",
"ijkl",
"infobip",
"intermediatereport",
"klass",
"motogstylus",
"msisdn",
"preserverecipients",
"pstn",
"pydantic",
"replyto",
"setuptools",
"smil",
"somexternal",
"templateid",
"testenv",
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/python-package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ['3.8', '3.9', '3.10']
python-version: ['3.8', '3.9', '3.10', '3.11']

steps:
- uses: actions/checkout@v2
Expand Down
3 changes: 2 additions & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,12 @@ repos:
rev: 23.1.0
hooks:
- id: black
args: ["--line-length", "88", "--target-version", "py39"]
args: ["--line-length", "88", "--target-version", "py310"]
- repo: https://github.com/pycqa/flake8
rev: 4.0.1
hooks:
- id: flake8
args:
- "--ignore=E501, W503"
exclude: "infobip/models/"
additional_dependencies: [flake8-print]
86 changes: 46 additions & 40 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,11 @@ once more authentication methods are included.
To install infobip SDK you will need to run:

```bash
pip install infobip-api-python-sdk
pip install infobip
```

Details of the package can be found
in the [PyPI page](https://pypi.org/project/infobip-api-python-sdk/).
in the [PyPI page](https://pypi.org/project/infobip/).

## 🚀 Usage

Expand All @@ -53,45 +53,51 @@ To use the package you'll need an Infobip account.
If you don't already have one, you can create a free trial account
[here](https://www.infobip.com/signup).

In this example, we will show how to send a WhatsApp text message.
In this example, we will show how to send an SMS message.
Other channels can be used in a similar way.
The first step is to import the necessary channel, in this case WhatsApp channel.
The first step is to import the Infobip API Client and needed models.
Then you can use a context manager to create the client, and use it to call the API.
After calling the endpoint, you can parse the response into a response body object.
This code needs that you previously set the environment variables `IB_BASE_URL` and `IB_API_KEY`.

```python
from infobip_channels.whatsapp.channel import WhatsAppChannel
```

Now you can create instance of `WhatsAppChannel` with your `base_url` and `api_key`.

```python
c = WhatsAppChannel.from_auth_params({
"base_url": "<your_base_url>",
"api_key": "<your_api_key>"
})
```

Alternatively, you can create the instance from the environment, having the `IB_BASE_URL` and `IB_API_KEY` variables
set, like this:

```python
c = WhatsAppChannel.from_env()
```

After that you can access all the methods from `WhatsAppChannel`.
To send text message you can use `send_text_message` method and add correct payload:
```python
response = c.send_text_message(
{
"from": "<WhatsApp sender number from your Infobib account>",
"to": "<Number that will receive WhatsApp message>",
"messageId": "a28dd97c-1ffb-4fcf-99f1-0b557ed381da",
"content": {
"text": "Some text"
},
"callbackData": "Callback data",
"notifyUrl": "https://www.example.com/whatsapp"
}
)
import asyncio
from infobip.client import APIClient
from infobip.models.sms_advanced_textual_request import SendSMSRequestBody
from infobip.models.sms_textual_message import Message
from infobip.models.sms_destination import Destination
from infobip.models.sms_response import SendSMSResponseBody


async def main():
async with APIClient() as client:
# Create a request body object and validate its contents.
request_body = SendSMSRequestBody(
messages=[
Message(
destinations=[
Destination(
to="555555555555",
),
],
text="Hello from Infobip Python SDK!",
)
]
)

# Call the endpoint and await returned Coroutine
response = await client.SMS.send(request_body)

# (Optional) Parse and validate response.
response_body = SendSMSResponseBody.from_json(response.text)

# Do something with the response.
print(response)
print(response_body)


if __name__ == "__main__":
asyncio.run(main())
```

### Samples
Expand All @@ -101,10 +107,10 @@ with real payloads.

## 🗒️ Notes

For `infobip-api-python-sdk` versioning we use
For SDK versioning we use
[Semantic Versioning](https://semver.org) scheme.

Python 3.6 is the minimum supported version by this library.
Python 3.8 is the minimum supported version by this library.

## 🧡 Want to help and improve this open-source SDK?

Expand Down
File renamed without changes.
File renamed without changes.
28 changes: 28 additions & 0 deletions infobip/api/mms.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
from typing import Awaitable

from httpx import AsyncClient, Response

from infobip.models.mms_get_inbound_messages_query_parameters import (
GetInboundMessagesQueryParameters,
)


class MMSClient:
PATH_GET_INBOUND_MESSAGES = "/mms/1/inbox/reports"

def __init__(self, client: AsyncClient):
self.client = client

def get_inbound_messages(
self,
query_parameters: GetInboundMessagesQueryParameters,
) -> Awaitable[Response]:
"""Get inbound messages

:param query_parameters: Query parameters for getting inbound messages
"""

return self.client.get(
self.PATH_GET_INBOUND_MESSAGES,
params=query_parameters.to_dict(),
)
61 changes: 61 additions & 0 deletions infobip/api/sms.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
from typing import Awaitable

from httpx import AsyncClient, Client, Response

from infobip.models.sms_advanced_textual_request import SendSMSRequestBody
from infobip.models.sms_preview_request import PreviewSMSRequestBody

PATH_PREVIEW_SMS = "/sms/1/preview"
PATH_SEND_SMS = "/sms/2/text/advanced"


class SMSClient:
def __init__(self, client: AsyncClient):
self.client = client
self.client.headers.update({"content-type": "application/json"})

def preview(self, request_body: PreviewSMSRequestBody) -> Awaitable[Response]:
"""Check how different message configurations will affect your message text, number of characters and message
parts.

:param request_body: Request body for previewing an SMS message
"""

return self.client.post(
PATH_PREVIEW_SMS,
json=request_body.to_dict(),
)

def send(
self,
request_body: SendSMSRequestBody,
) -> Awaitable[Response]:
"""Send an SMS message. You can send a simple single message to a single destination, up to batch sending of
personalized messages to the thousands of recipients with a single API request. Language, transliteration,
scheduling and every advanced feature you can think of is supported.

:param request_body: Request body for sending an SMS message
"""

return self.client.post(
PATH_SEND_SMS,
json=request_body.to_dict(),
)


class SyncSMSClient:
def __init__(self, client: Client):
self._client = client
self._client.headers.update({"content-type": "application/json"})

def preview(self, request_body: PreviewSMSRequestBody) -> Response:
"""Check how different message configurations will affect your message text, number of characters and message
parts. This is a synchronous version of the method.

:param request_body: Request body for previewing an SMS message
"""

return self._client.post(
PATH_PREVIEW_SMS,
json=request_body.to_dict(),
)
40 changes: 40 additions & 0 deletions infobip/client.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import importlib.metadata
import sys
from os import getenv

from httpx import AsyncClient

from infobip.api.mms import MMSClient
from infobip.api.sms import SMSClient


def _get_user_agent() -> str:
return f"@infobip/python-sdk{_get_package_version()} python/{sys.version.split(' ')[0]}"


def _get_package_version() -> str:
sdk_version = ""
if "infobip_channels" in sys.modules:
try:
sdk_version = "/" + importlib.metadata.distribution("infobip").version
except importlib.metadata.PackageNotFoundError:
# Ignore as package is not installed in development environment.
pass

return sdk_version


class APIClient(AsyncClient):
def __init__(self, base_url: str = None, api_key: str = None):
if base_url is None:
base_url = getenv("IB_BASE_URL")
if api_key is None:
api_key = getenv("IB_API_KEY")

headers = {"Authorization": f"App {api_key}"}
headers.update({"User-Agent": _get_user_agent()})

super().__init__(base_url=base_url, headers=headers)

self.SMS = SMSClient(self)
self.MMS = MMSClient(self)
14 changes: 14 additions & 0 deletions infobip/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# coding: utf-8

# flake8: noqa
"""
This class is auto generated from the Infobip OpenAPI specification
through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR),
powered by the OpenAPI Generator (https://openapi-generator.tech).
"""


from __future__ import absolute_import

# import models into model package
from infobip.models.entity import Entity
Loading