diff --git a/.github/workflows/pypi.yml b/.github/workflows/pypi.yml new file mode 100644 index 0000000..dff71f3 --- /dev/null +++ b/.github/workflows/pypi.yml @@ -0,0 +1,95 @@ +name: Publish Python 🐍 distribution 📦 to PyPI and TestPyPI + +on: push + +jobs: + build: + name: Build distribution 📦 + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + with: + persist-credentials: false + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.x" + - name: Install pypa/build + run: >- + python3 -m + pip install + build + --user + - name: Build a binary wheel and a source tarball + run: python3 -m build + - name: Store the distribution packages + uses: actions/upload-artifact@v4 + with: + name: python-package-distributions + path: dist/ + + publish-to-pypi: + name: >- + Publish Python 🐍 distribution 📦 to PyPI + if: startsWith(github.ref, 'refs/tags/') # only publish to PyPI on tag pushes + needs: + - build + runs-on: ubuntu-latest + environment: + name: pypi + url: https://pypi.org/p/messente-api # Replace with your PyPI project name + permissions: + id-token: write # IMPORTANT: mandatory for trusted publishing + + steps: + - name: Download all the dists + uses: actions/download-artifact@v4 + with: + name: python-package-distributions + path: dist/ + - name: Publish distribution 📦 to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 + + github-release: + name: >- + Sign the Python 🐍 distribution 📦 with Sigstore + and upload them to GitHub Release + needs: + - publish-to-pypi + runs-on: ubuntu-latest + + permissions: + contents: write # IMPORTANT: mandatory for making GitHub Releases + id-token: write # IMPORTANT: mandatory for sigstore + + steps: + - name: Download all the dists + uses: actions/download-artifact@v4 + with: + name: python-package-distributions + path: dist/ + - name: Sign the dists with Sigstore + uses: sigstore/gh-action-sigstore-python@v3.0.0 + with: + inputs: >- + ./dist/*.tar.gz + ./dist/*.whl + - name: Create GitHub Release + env: + GITHUB_TOKEN: ${{ github.token }} + run: >- + gh release create + "$GITHUB_REF_NAME" + --repo "$GITHUB_REPOSITORY" + --notes "" + - name: Upload artifact signatures to GitHub Release + env: + GITHUB_TOKEN: ${{ github.token }} + # Upload to GitHub Release using the `gh` CLI. + # `dist/` contains the built packages, and the + # sigstore-produced signatures and certificates. + run: >- + gh release upload + "$GITHUB_REF_NAME" dist/** + --repo "$GITHUB_REPOSITORY" \ No newline at end of file diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml deleted file mode 100644 index 996834f..0000000 --- a/.github/workflows/python.yml +++ /dev/null @@ -1,38 +0,0 @@ -# NOTE: This file is auto generated by OpenAPI Generator. -# URL: https://openapi-generator.tech -# -# ref: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python - -name: messente_api Python package - -on: [push, pull_request] - -jobs: - build: - - runs-on: ubuntu-latest - strategy: - matrix: - python-version: ["3.7", "3.8", "3.9", "3.10", "3.11"] - - steps: - - uses: actions/checkout@v3 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v4 - with: - python-version: ${{ matrix.python-version }} - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install flake8 pytest - if [ -f requirements.txt ]; then pip install -r requirements.txt; fi - if [ -f test-requirements.txt ]; then pip install -r test-requirements.txt; fi - - name: Lint with flake8 - run: | - # stop the build if there are Python syntax errors or undefined names - flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics - # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide - flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics - - name: Test with pytest - run: | - pytest diff --git a/.openapi-generator/FILES b/.openapi-generator/FILES index 321050b..d62c762 100644 --- a/.openapi-generator/FILES +++ b/.openapi-generator/FILES @@ -71,6 +71,7 @@ docs/WhatsAppLanguage.md docs/WhatsAppMedia.md docs/WhatsAppParameter.md docs/WhatsAppTemplate.md +docs/WhatsAppText.md git_push.sh messente_api/__init__.py messente_api/api/__init__.py @@ -146,6 +147,7 @@ messente_api/models/whats_app_language.py messente_api/models/whats_app_media.py messente_api/models/whats_app_parameter.py messente_api/models/whats_app_template.py +messente_api/models/whats_app_text.py messente_api/py.typed messente_api/rest.py pyproject.toml diff --git a/.travis.yml b/.travis.yml index 1b62c4f..f77cf2c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,7 @@ language: python +dist: jammy +python: + - 3.10 script: - echo "skipping tests" diff --git a/README.md b/README.md index f0e5299..2f2a5e7 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # Messente API Library - Messente API version: 2.0.0 -- Python package version: 2.2.0 +- Python package version: 2.3.0 [Messente](https://messente.com) is a global provider of messaging and user verification services. * Send and receive SMS, Viber, WhatsApp and Telegram messages. * Manage contacts and groups. * Fetch detailed info about phone numbers. * Blacklist phone numbers to make sure you're not sending any unwanted messages. Messente builds [tools](https://messente.com/documentation) to help organizations connect their services to people anywhere in the world. diff --git a/docs/WhatsApp.md b/docs/WhatsApp.md index e26fc56..f402db3 100644 --- a/docs/WhatsApp.md +++ b/docs/WhatsApp.md @@ -10,6 +10,7 @@ Name | Type | Description | Notes **validity** | **int** | After how many minutes this channel is considered as failed and the next channel is attempted | [optional] **ttl** | **int** | After how many seconds this channel is considered as failed and the next channel is attempted. Only one of \"ttl\" and \"validity\" can be used. | [optional] **template** | [**WhatsAppTemplate**](WhatsAppTemplate.md) | | [optional] +**text** | [**WhatsAppText**](WhatsAppText.md) | | [optional] **channel** | **str** | The channel used to deliver the message | [optional] [default to 'whatsapp'] ## Example diff --git a/docs/WhatsAppParameter.md b/docs/WhatsAppParameter.md index 6ec3370..8dfb0c2 100644 --- a/docs/WhatsAppParameter.md +++ b/docs/WhatsAppParameter.md @@ -13,6 +13,8 @@ Name | Type | Description | Notes **image** | [**WhatsAppMedia**](WhatsAppMedia.md) | | [optional] **document** | [**WhatsAppMedia**](WhatsAppMedia.md) | | [optional] **video** | [**WhatsAppMedia**](WhatsAppMedia.md) | | [optional] +**coupon_code** | **str** | A coupon code. | [optional] +**payload** | **str** | A payload. | [optional] ## Example diff --git a/docs/WhatsAppText.md b/docs/WhatsAppText.md new file mode 100644 index 0000000..632a74c --- /dev/null +++ b/docs/WhatsAppText.md @@ -0,0 +1,31 @@ +# WhatsAppText + +A text + +## Properties + +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**preview_url** | **bool** | Whether to display link preview if the message contains a hyperlink | [optional] [default to True] +**body** | **str** | Plaintext content for WhatsApp, can contain URLs, emojis and formatting | + +## Example + +```python +from messente_api.models.whats_app_text import WhatsAppText + +# TODO update the JSON string below +json = "{}" +# create an instance of WhatsAppText from a JSON string +whats_app_text_instance = WhatsAppText.from_json(json) +# print the JSON string representation of the object +print(WhatsAppText.to_json()) + +# convert the object into a dict +whats_app_text_dict = whats_app_text_instance.to_dict() +# create an instance of WhatsAppText from a dict +whats_app_text_from_dict = WhatsAppText.from_dict(whats_app_text_dict) +``` +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/messente_api/__init__.py b/messente_api/__init__.py index 6246aaf..383d47a 100644 --- a/messente_api/__init__.py +++ b/messente_api/__init__.py @@ -15,7 +15,7 @@ """ # noqa: E501 -__version__ = "2.2.0" +__version__ = "2.3.0" # import apis into sdk package from messente_api.api.blacklist_api import BlacklistApi @@ -98,3 +98,4 @@ from messente_api.models.whats_app_media import WhatsAppMedia from messente_api.models.whats_app_parameter import WhatsAppParameter from messente_api.models.whats_app_template import WhatsAppTemplate +from messente_api.models.whats_app_text import WhatsAppText diff --git a/messente_api/api_client.py b/messente_api/api_client.py index 872c120..10c316b 100644 --- a/messente_api/api_client.py +++ b/messente_api/api_client.py @@ -89,7 +89,7 @@ def __init__( self.default_headers[header_name] = header_value self.cookie = cookie # Set default User-Agent. - self.user_agent = 'OpenAPI-Generator/2.2.0/python' + self.user_agent = 'OpenAPI-Generator/2.3.0/python' self.client_side_validation = configuration.client_side_validation def __enter__(self): diff --git a/messente_api/configuration.py b/messente_api/configuration.py index 9e082f1..1ba45fc 100644 --- a/messente_api/configuration.py +++ b/messente_api/configuration.py @@ -395,7 +395,7 @@ def to_debug_report(self): "OS: {env}\n"\ "Python Version: {pyversion}\n"\ "Version of the API: 2.0.0\n"\ - "SDK Package Version: 2.2.0".\ + "SDK Package Version: 2.3.0".\ format(env=sys.platform, pyversion=sys.version) def get_host_settings(self): diff --git a/messente_api/models/__init__.py b/messente_api/models/__init__.py index c6316d0..57fc05d 100644 --- a/messente_api/models/__init__.py +++ b/messente_api/models/__init__.py @@ -74,3 +74,4 @@ from messente_api.models.whats_app_media import WhatsAppMedia from messente_api.models.whats_app_parameter import WhatsAppParameter from messente_api.models.whats_app_template import WhatsAppTemplate +from messente_api.models.whats_app_text import WhatsAppText diff --git a/messente_api/models/whats_app.py b/messente_api/models/whats_app.py index affa10d..9f8cca7 100644 --- a/messente_api/models/whats_app.py +++ b/messente_api/models/whats_app.py @@ -21,6 +21,7 @@ from pydantic import BaseModel, ConfigDict, Field, StrictInt, StrictStr, field_validator from typing import Any, ClassVar, Dict, List, Optional from messente_api.models.whats_app_template import WhatsAppTemplate +from messente_api.models.whats_app_text import WhatsAppText from typing import Optional, Set from typing_extensions import Self @@ -32,9 +33,10 @@ class WhatsApp(BaseModel): validity: Optional[StrictInt] = Field(default=None, description="After how many minutes this channel is considered as failed and the next channel is attempted") ttl: Optional[StrictInt] = Field(default=None, description="After how many seconds this channel is considered as failed and the next channel is attempted. Only one of \"ttl\" and \"validity\" can be used.") template: Optional[WhatsAppTemplate] = None + text: Optional[WhatsAppText] = None channel: Optional[StrictStr] = Field(default='whatsapp', description="The channel used to deliver the message") additional_properties: Dict[str, Any] = {} - __properties: ClassVar[List[str]] = ["sender", "validity", "ttl", "template", "channel"] + __properties: ClassVar[List[str]] = ["sender", "validity", "ttl", "template", "text", "channel"] @field_validator('channel') def channel_validate_enum(cls, value): @@ -90,6 +92,9 @@ def to_dict(self) -> Dict[str, Any]: # override the default output from pydantic by calling `to_dict()` of template if self.template: _dict['template'] = self.template.to_dict() + # override the default output from pydantic by calling `to_dict()` of text + if self.text: + _dict['text'] = self.text.to_dict() # puts key-value pairs in additional_properties in the top level if self.additional_properties is not None: for _key, _value in self.additional_properties.items(): @@ -111,6 +116,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "validity": obj.get("validity"), "ttl": obj.get("ttl"), "template": WhatsAppTemplate.from_dict(obj["template"]) if obj.get("template") is not None else None, + "text": WhatsAppText.from_dict(obj["text"]) if obj.get("text") is not None else None, "channel": obj.get("channel") if obj.get("channel") is not None else 'whatsapp' }) # store additional fields in additional_properties diff --git a/messente_api/models/whats_app_parameter.py b/messente_api/models/whats_app_parameter.py index dd3a98b..2a6e765 100644 --- a/messente_api/models/whats_app_parameter.py +++ b/messente_api/models/whats_app_parameter.py @@ -37,8 +37,10 @@ class WhatsAppParameter(BaseModel): image: Optional[WhatsAppMedia] = None document: Optional[WhatsAppMedia] = None video: Optional[WhatsAppMedia] = None + coupon_code: Optional[StrictStr] = Field(default=None, description="A coupon code.") + payload: Optional[StrictStr] = Field(default=None, description="A payload.") additional_properties: Dict[str, Any] = {} - __properties: ClassVar[List[str]] = ["type", "text", "currency", "date_time", "image", "document", "video"] + __properties: ClassVar[List[str]] = ["type", "text", "currency", "date_time", "image", "document", "video", "coupon_code", "payload"] model_config = ConfigDict( populate_by_name=True, @@ -119,7 +121,9 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "date_time": WhatsAppDatetime.from_dict(obj["date_time"]) if obj.get("date_time") is not None else None, "image": WhatsAppMedia.from_dict(obj["image"]) if obj.get("image") is not None else None, "document": WhatsAppMedia.from_dict(obj["document"]) if obj.get("document") is not None else None, - "video": WhatsAppMedia.from_dict(obj["video"]) if obj.get("video") is not None else None + "video": WhatsAppMedia.from_dict(obj["video"]) if obj.get("video") is not None else None, + "coupon_code": obj.get("coupon_code"), + "payload": obj.get("payload") }) # store additional fields in additional_properties for _key in obj.keys(): diff --git a/messente_api/models/whats_app_text.py b/messente_api/models/whats_app_text.py new file mode 100644 index 0000000..07a4b27 --- /dev/null +++ b/messente_api/models/whats_app_text.py @@ -0,0 +1,103 @@ +# coding: utf-8 + +""" + Messente API + + [Messente](https://messente.com) is a global provider of messaging and user verification services. * Send and receive SMS, Viber, WhatsApp and Telegram messages. * Manage contacts and groups. * Fetch detailed info about phone numbers. * Blacklist phone numbers to make sure you're not sending any unwanted messages. Messente builds [tools](https://messente.com/documentation) to help organizations connect their services to people anywhere in the world. + + The version of the OpenAPI document: 2.0.0 + Contact: messente@messente.com + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from typing import Optional, Set +from typing_extensions import Self + +class WhatsAppText(BaseModel): + """ + A text + """ # noqa: E501 + preview_url: Optional[StrictBool] = Field(default=True, description="Whether to display link preview if the message contains a hyperlink") + body: StrictStr = Field(description="Plaintext content for WhatsApp, can contain URLs, emojis and formatting") + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["preview_url", "body"] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of WhatsAppText from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of WhatsAppText from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "preview_url": obj.get("preview_url") if obj.get("preview_url") is not None else True, + "body": obj.get("body") + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/pyproject.toml b/pyproject.toml index 8100fc5..c98b034 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "messente_api" -version = "2.2.0" +version = "2.3.0" description = "Messente API" authors = ["Messente "] license = "Apache-2.0" diff --git a/setup.py b/setup.py index 612c735..7da0a8b 100644 --- a/setup.py +++ b/setup.py @@ -22,7 +22,7 @@ # prerequisite: setuptools # http://pypi.python.org/pypi/setuptools NAME = "messente-api" -VERSION = "2.2.0" +VERSION = "2.3.0" PYTHON_REQUIRES = ">=3.7" REQUIRES = [ "urllib3 >= 1.25.3, < 2.1.0",