letschatty 0.1.44__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- letschatty-0.1.44/LICENSE +18 -0
- letschatty-0.1.44/PKG-INFO +37 -0
- letschatty-0.1.44/README.md +20 -0
- letschatty-0.1.44/pyproject.toml +19 -0
- letschatty-0.1.44/src/letschatty/__init__.py +2 -0
- letschatty-0.1.44/src/letschatty/models/__init__.py +4 -0
- letschatty-0.1.44/src/letschatty/models/company/empresa.py +11 -0
- letschatty-0.1.44/src/letschatty/models/events/__init__.py +6 -0
- letschatty-0.1.44/src/letschatty/models/events/__pycache__/__init__.cpython-311.pyc +0 -0
- letschatty-0.1.44/src/letschatty/models/events/base.py +45 -0
- letschatty-0.1.44/src/letschatty/models/events/contact_point.py +18 -0
- letschatty-0.1.44/src/letschatty/models/events/event_types.py +11 -0
- letschatty-0.1.44/src/letschatty/models/events/new_chat.py +11 -0
- letschatty-0.1.44/src/letschatty/models/events/quality_scoring.py +16 -0
- letschatty-0.1.44/src/letschatty/models/events/sale.py +16 -0
- letschatty-0.1.44/src/letschatty/models/events/template.py +19 -0
- letschatty-0.1.44/src/letschatty/models/messages/__init__.py +2 -0
- letschatty-0.1.44/src/letschatty/models/messages/chatty_messages/__init__.py +17 -0
- letschatty-0.1.44/src/letschatty/models/messages/chatty_messages/__pycache__/__init__.cpython-311.pyc +0 -0
- letschatty-0.1.44/src/letschatty/models/messages/chatty_messages/__pycache__/audio.cpython-311.pyc +0 -0
- letschatty-0.1.44/src/letschatty/models/messages/chatty_messages/__pycache__/button.cpython-311.pyc +0 -0
- letschatty-0.1.44/src/letschatty/models/messages/chatty_messages/__pycache__/central_notification.cpython-311.pyc +0 -0
- letschatty-0.1.44/src/letschatty/models/messages/chatty_messages/__pycache__/contact.cpython-311.pyc +0 -0
- letschatty-0.1.44/src/letschatty/models/messages/chatty_messages/__pycache__/document.cpython-311.pyc +0 -0
- letschatty-0.1.44/src/letschatty/models/messages/chatty_messages/__pycache__/image.cpython-311.pyc +0 -0
- letschatty-0.1.44/src/letschatty/models/messages/chatty_messages/__pycache__/location.cpython-311.pyc +0 -0
- letschatty-0.1.44/src/letschatty/models/messages/chatty_messages/__pycache__/reaction.cpython-311.pyc +0 -0
- letschatty-0.1.44/src/letschatty/models/messages/chatty_messages/__pycache__/sticker.cpython-311.pyc +0 -0
- letschatty-0.1.44/src/letschatty/models/messages/chatty_messages/__pycache__/sticket.cpython-311.pyc +0 -0
- letschatty-0.1.44/src/letschatty/models/messages/chatty_messages/__pycache__/text.cpython-311.pyc +0 -0
- letschatty-0.1.44/src/letschatty/models/messages/chatty_messages/__pycache__/unsupported.cpython-311.pyc +0 -0
- letschatty-0.1.44/src/letschatty/models/messages/chatty_messages/__pycache__/video.cpython-311.pyc +0 -0
- letschatty-0.1.44/src/letschatty/models/messages/chatty_messages/audio.py +7 -0
- letschatty-0.1.44/src/letschatty/models/messages/chatty_messages/base/__init__.py +1 -0
- letschatty-0.1.44/src/letschatty/models/messages/chatty_messages/base/__pycache__/__init__.cpython-311.pyc +0 -0
- letschatty-0.1.44/src/letschatty/models/messages/chatty_messages/base/__pycache__/message_base.cpython-311.pyc +0 -0
- letschatty-0.1.44/src/letschatty/models/messages/chatty_messages/base/chatty_message_json.py +22 -0
- letschatty-0.1.44/src/letschatty/models/messages/chatty_messages/base/message_base.py +117 -0
- letschatty-0.1.44/src/letschatty/models/messages/chatty_messages/button.py +7 -0
- letschatty-0.1.44/src/letschatty/models/messages/chatty_messages/central_notification.py +8 -0
- letschatty-0.1.44/src/letschatty/models/messages/chatty_messages/contact.py +7 -0
- letschatty-0.1.44/src/letschatty/models/messages/chatty_messages/document.py +7 -0
- letschatty-0.1.44/src/letschatty/models/messages/chatty_messages/image.py +7 -0
- letschatty-0.1.44/src/letschatty/models/messages/chatty_messages/interactive.py +6 -0
- letschatty-0.1.44/src/letschatty/models/messages/chatty_messages/location.py +7 -0
- letschatty-0.1.44/src/letschatty/models/messages/chatty_messages/reaction.py +7 -0
- letschatty-0.1.44/src/letschatty/models/messages/chatty_messages/schema/__init__.py +18 -0
- letschatty-0.1.44/src/letschatty/models/messages/chatty_messages/schema/__pycache__/__init__.cpython-311.pyc +0 -0
- letschatty-0.1.44/src/letschatty/models/messages/chatty_messages/schema/__pycache__/content_audio.cpython-311.pyc +0 -0
- letschatty-0.1.44/src/letschatty/models/messages/chatty_messages/schema/__pycache__/content_central.cpython-311.pyc +0 -0
- letschatty-0.1.44/src/letschatty/models/messages/chatty_messages/schema/__pycache__/content_contacts.cpython-311.pyc +0 -0
- letschatty-0.1.44/src/letschatty/models/messages/chatty_messages/schema/__pycache__/content_document.cpython-311.pyc +0 -0
- letschatty-0.1.44/src/letschatty/models/messages/chatty_messages/schema/__pycache__/content_image.cpython-311.pyc +0 -0
- letschatty-0.1.44/src/letschatty/models/messages/chatty_messages/schema/__pycache__/content_location.cpython-311.pyc +0 -0
- letschatty-0.1.44/src/letschatty/models/messages/chatty_messages/schema/__pycache__/content_reaction.cpython-311.pyc +0 -0
- letschatty-0.1.44/src/letschatty/models/messages/chatty_messages/schema/__pycache__/content_sticker.cpython-311.pyc +0 -0
- letschatty-0.1.44/src/letschatty/models/messages/chatty_messages/schema/__pycache__/content_text.cpython-311.pyc +0 -0
- letschatty-0.1.44/src/letschatty/models/messages/chatty_messages/schema/__pycache__/content_video.cpython-311.pyc +0 -0
- letschatty-0.1.44/src/letschatty/models/messages/chatty_messages/schema/chatty_content/content_audio.py +6 -0
- letschatty-0.1.44/src/letschatty/models/messages/chatty_messages/schema/chatty_content/content_central.py +5 -0
- letschatty-0.1.44/src/letschatty/models/messages/chatty_messages/schema/chatty_content/content_contacts.py +21 -0
- letschatty-0.1.44/src/letschatty/models/messages/chatty_messages/schema/chatty_content/content_document.py +8 -0
- letschatty-0.1.44/src/letschatty/models/messages/chatty_messages/schema/chatty_content/content_image.py +4 -0
- letschatty-0.1.44/src/letschatty/models/messages/chatty_messages/schema/chatty_content/content_location.py +5 -0
- letschatty-0.1.44/src/letschatty/models/messages/chatty_messages/schema/chatty_content/content_media.py +8 -0
- letschatty-0.1.44/src/letschatty/models/messages/chatty_messages/schema/chatty_content/content_reaction.py +4 -0
- letschatty-0.1.44/src/letschatty/models/messages/chatty_messages/schema/chatty_content/content_sticker.py +6 -0
- letschatty-0.1.44/src/letschatty/models/messages/chatty_messages/schema/chatty_content/content_text.py +5 -0
- letschatty-0.1.44/src/letschatty/models/messages/chatty_messages/schema/chatty_content/content_video.py +5 -0
- letschatty-0.1.44/src/letschatty/models/messages/chatty_messages/schema/chatty_context/__init__.py +0 -0
- letschatty-0.1.44/src/letschatty/models/messages/chatty_messages/schema/chatty_context/__pycache__/chatty_context.cpython-311.pyc +0 -0
- letschatty-0.1.44/src/letschatty/models/messages/chatty_messages/schema/chatty_context/chatty_context.py +22 -0
- letschatty-0.1.44/src/letschatty/models/messages/chatty_messages/schema/chatty_referal/__init__.py +0 -0
- letschatty-0.1.44/src/letschatty/models/messages/chatty_messages/schema/chatty_referal/chatty_referal.py +37 -0
- letschatty-0.1.44/src/letschatty/models/messages/chatty_messages/sticker.py +7 -0
- letschatty-0.1.44/src/letschatty/models/messages/chatty_messages/text.py +7 -0
- letschatty-0.1.44/src/letschatty/models/messages/chatty_messages/unknown.py +6 -0
- letschatty-0.1.44/src/letschatty/models/messages/chatty_messages/unsupported.py +5 -0
- letschatty-0.1.44/src/letschatty/models/messages/chatty_messages/video.py +7 -0
- letschatty-0.1.44/src/letschatty/models/messages/messages_request/__init__.py +1 -0
- letschatty-0.1.44/src/letschatty/models/messages/messages_request/__pycache__/message_request.cpython-311.pyc +0 -0
- letschatty-0.1.44/src/letschatty/models/messages/messages_request/message_request.py +22 -0
- letschatty-0.1.44/src/letschatty/models/messages/meta_message_model/__pycache__/meta_base_notification_json.cpython-311.pyc +0 -0
- letschatty-0.1.44/src/letschatty/models/messages/meta_message_model/__pycache__/meta_error_json.cpython-311.pyc +0 -0
- letschatty-0.1.44/src/letschatty/models/messages/meta_message_model/__pycache__/meta_inexistent_json.cpython-311.pyc +0 -0
- letschatty-0.1.44/src/letschatty/models/messages/meta_message_model/__pycache__/meta_message_json.cpython-311.pyc +0 -0
- letschatty-0.1.44/src/letschatty/models/messages/meta_message_model/__pycache__/meta_message_types.cpython-311.pyc +0 -0
- letschatty-0.1.44/src/letschatty/models/messages/meta_message_model/__pycache__/meta_status_json.cpython-311.pyc +0 -0
- letschatty-0.1.44/src/letschatty/models/messages/meta_message_model/__pycache__/meta_unknown_json.cpython-311.pyc +0 -0
- letschatty-0.1.44/src/letschatty/models/messages/meta_message_model/meta_base_notification_json.py +64 -0
- letschatty-0.1.44/src/letschatty/models/messages/meta_message_model/meta_error_json.py +10 -0
- letschatty-0.1.44/src/letschatty/models/messages/meta_message_model/meta_inexistent_json.py +5 -0
- letschatty-0.1.44/src/letschatty/models/messages/meta_message_model/meta_message_json.py +142 -0
- letschatty-0.1.44/src/letschatty/models/messages/meta_message_model/meta_message_types.py +126 -0
- letschatty-0.1.44/src/letschatty/models/messages/meta_message_model/meta_status_json.py +85 -0
- letschatty-0.1.44/src/letschatty/models/messages/meta_message_model/meta_unknown_json.py +5 -0
- letschatty-0.1.44/src/letschatty/models/metrics/__init_.py +5 -0
- letschatty-0.1.44/src/letschatty/models/metrics/daily_contact_points.py +21 -0
- letschatty-0.1.44/src/letschatty/models/metrics/daily_new_chats.py +12 -0
- letschatty-0.1.44/src/letschatty/models/metrics/daily_sent_templates_grouped.py +21 -0
- letschatty-0.1.44/src/letschatty/models/metrics/sales_roadmap.py +15 -0
- letschatty-0.1.44/src/letschatty/models/metrics/sent_templates.py +19 -0
- letschatty-0.1.44/src/letschatty/models/utils/__init__.py +1 -0
- letschatty-0.1.44/src/letschatty/models/utils/__pycache__/__init__.cpython-311.pyc +0 -0
- letschatty-0.1.44/src/letschatty/models/utils/types/__init__.py +8 -0
- letschatty-0.1.44/src/letschatty/models/utils/types/__pycache__/__init__.cpython-311.pyc +0 -0
- letschatty-0.1.44/src/letschatty/models/utils/types/__pycache__/country.cpython-311.pyc +0 -0
- letschatty-0.1.44/src/letschatty/models/utils/types/__pycache__/identifier.cpython-311.pyc +0 -0
- letschatty-0.1.44/src/letschatty/models/utils/types/__pycache__/message_statuses.cpython-311.pyc +0 -0
- letschatty-0.1.44/src/letschatty/models/utils/types/__pycache__/phone_number.cpython-311.pyc +0 -0
- letschatty-0.1.44/src/letschatty/models/utils/types/__pycache__/source_types.cpython-311.pyc +0 -0
- letschatty-0.1.44/src/letschatty/models/utils/types/__pycache__/typealiases.cpython-311.pyc +0 -0
- letschatty-0.1.44/src/letschatty/models/utils/types/channel_types.py +5 -0
- letschatty-0.1.44/src/letschatty/models/utils/types/country.py +20 -0
- letschatty-0.1.44/src/letschatty/models/utils/types/identifier.py +15 -0
- letschatty-0.1.44/src/letschatty/models/utils/types/message_status_types.py +8 -0
- letschatty-0.1.44/src/letschatty/models/utils/types/message_types.py +20 -0
- letschatty-0.1.44/src/letschatty/models/utils/types/phone_number.py +14 -0
- letschatty-0.1.44/src/letschatty/models/utils/types/source_types.py +9 -0
- letschatty-0.1.44/src/letschatty/models/utils/types/typealiases.py +1 -0
- letschatty-0.1.44/src/letschatty/services/factories/__init__.py +1 -0
- letschatty-0.1.44/src/letschatty/services/factories/child_chatty_message_factory.py +1 -0
- letschatty-0.1.44/src/letschatty/services/factories/child_db_message_factory.py +108 -0
- letschatty-0.1.44/src/letschatty/services/factories/child_request_message.py +97 -0
- letschatty-0.1.44/src/letschatty/services/factories/parent_message_factory.py +18 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
Proprietary and Confidential
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Axel Gualda. All Rights Reserved.
|
|
4
|
+
|
|
5
|
+
This software, known as "Chatty Analytics", and its documentation are the proprietary and confidential
|
|
6
|
+
property of Axel Gualda. The software is provided solely for the use of authorized individuals in
|
|
7
|
+
accordance with their duties and obligations related to Chatty Analytics.
|
|
8
|
+
|
|
9
|
+
Unauthorized copying, distribution, modification, public display, or public performance of this software,
|
|
10
|
+
its documentation, or any portion thereof is strictly prohibited. Proprietary and confidential information
|
|
11
|
+
contained within the software may not be copied, distributed, modified, or disclosed to any third party
|
|
12
|
+
without the prior written consent of Axel Gualda.
|
|
13
|
+
|
|
14
|
+
This software is provided "AS IS", without warranty of any kind, express or implied, including but not
|
|
15
|
+
limited to the warranties of merchantability, fitness for a particular purpose and non-infringement.
|
|
16
|
+
In no event shall the author or copyright holder be liable for any claim, damages or other liability,
|
|
17
|
+
whether in an action of contract, tort or otherwise, arising from, out of or in connection with the
|
|
18
|
+
software or the use or other dealings in the software.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: letschatty
|
|
3
|
+
Version: 0.1.44
|
|
4
|
+
Summary: Models and custom classes to work across the Chattyverse
|
|
5
|
+
License: MIT
|
|
6
|
+
Author: Axel
|
|
7
|
+
Author-email: axel@letschatty.com
|
|
8
|
+
Requires-Python: >=3.11,<4.0
|
|
9
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
13
|
+
Requires-Dist: pycountry (>=24.6.1,<25.0.0)
|
|
14
|
+
Requires-Dist: pydantic (>=2.9.2,<3.0.0)
|
|
15
|
+
Requires-Dist: pymongo (>=4.10.1,<5.0.0)
|
|
16
|
+
Description-Content-Type: text/markdown
|
|
17
|
+
|
|
18
|
+
# Chatty Analytics
|
|
19
|
+
Models and custom classes to work across the Chattyverse
|
|
20
|
+
|
|
21
|
+
Chatty Analytics is a proprietary tool developed by Axel Gualda. This software is for internal use only and is not licensed for distribution or use outside of authorized contexts.
|
|
22
|
+
|
|
23
|
+
Copyright (c) 2024 Axel Gualda. All Rights Reserved.
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
poetry version patch
|
|
27
|
+
poetry build
|
|
28
|
+
poetry publish -r testpypi
|
|
29
|
+
pip cache purge
|
|
30
|
+
pip uninstall letschatty -y
|
|
31
|
+
pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple letschatty
|
|
32
|
+
pytest -v tests/unit/models/messages/test_message_from_db.py
|
|
33
|
+
|
|
34
|
+
pip cache purge
|
|
35
|
+
pip uninstall letschatty -y
|
|
36
|
+
pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple letschatty
|
|
37
|
+
pytest -v tests/unit/models/messages/test_message_from_db.py
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Chatty Analytics
|
|
2
|
+
Models and custom classes to work across the Chattyverse
|
|
3
|
+
|
|
4
|
+
Chatty Analytics is a proprietary tool developed by Axel Gualda. This software is for internal use only and is not licensed for distribution or use outside of authorized contexts.
|
|
5
|
+
|
|
6
|
+
Copyright (c) 2024 Axel Gualda. All Rights Reserved.
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
poetry version patch
|
|
10
|
+
poetry build
|
|
11
|
+
poetry publish -r testpypi
|
|
12
|
+
pip cache purge
|
|
13
|
+
pip uninstall letschatty -y
|
|
14
|
+
pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple letschatty
|
|
15
|
+
pytest -v tests/unit/models/messages/test_message_from_db.py
|
|
16
|
+
|
|
17
|
+
pip cache purge
|
|
18
|
+
pip uninstall letschatty -y
|
|
19
|
+
pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple letschatty
|
|
20
|
+
pytest -v tests/unit/models/messages/test_message_from_db.py
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
[tool.poetry]
|
|
2
|
+
name = "letschatty"
|
|
3
|
+
version = "0.1.44" # Or whichever is your latest version
|
|
4
|
+
description = "Models and custom classes to work across the Chattyverse"
|
|
5
|
+
authors = ["Axel <axel@letschatty.com>"]
|
|
6
|
+
license = "MIT"
|
|
7
|
+
readme = "README.md"
|
|
8
|
+
packages = [{include = "letschatty", from = "src"}]
|
|
9
|
+
|
|
10
|
+
[tool.poetry.dependencies]
|
|
11
|
+
python = "^3.11"
|
|
12
|
+
pymongo = "^4.10.1"
|
|
13
|
+
pydantic = "^2.9.2"
|
|
14
|
+
pycountry = "^24.6.1"
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
[build-system]
|
|
18
|
+
requires = ["poetry-core"]
|
|
19
|
+
build-backend = "poetry.core.masonry.api"
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
from pydantic import BaseModel, Field
|
|
2
|
+
from typing import Optional
|
|
3
|
+
|
|
4
|
+
class Empresa(BaseModel):
|
|
5
|
+
name: str
|
|
6
|
+
phone_number_id: str = Field(alias="company_id")
|
|
7
|
+
bussiness_account_id: str
|
|
8
|
+
photo_url: str
|
|
9
|
+
meta_token: str
|
|
10
|
+
slack_channel_id: Optional[str] = Field(default=None)
|
|
11
|
+
phone_numbers_for_testing: list[str] = Field(default=[])
|
|
Binary file
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
from pydantic import BaseModel, Field
|
|
2
|
+
from enum import StrEnum
|
|
3
|
+
from bson import ObjectId
|
|
4
|
+
from datetime import datetime, timezone
|
|
5
|
+
from typing import Dict, Any
|
|
6
|
+
from .event_types import EventType
|
|
7
|
+
from ..utils.types.identifier import StrObjectId
|
|
8
|
+
import re
|
|
9
|
+
|
|
10
|
+
class ChattyCloudEvent(BaseModel):
|
|
11
|
+
id: StrObjectId = Field(default_factory=lambda: str(ObjectId()), alias="_id")
|
|
12
|
+
source: str = Field(..., pattern=r"com\.chatty/[a-z-]+/[a-zA-Z0-9-]+")
|
|
13
|
+
specversion: str = Field(default="1.0")
|
|
14
|
+
type: EventType
|
|
15
|
+
time: datetime = Field(default_factory=lambda: datetime.now(tz=timezone.utc))
|
|
16
|
+
datacontenttype: str = Field(default="application/json")
|
|
17
|
+
data: Dict[str, Any]
|
|
18
|
+
|
|
19
|
+
class ClientEvent(ChattyCloudEvent):
|
|
20
|
+
"""Used for client related events, either management wise like an agent event or a business logic event like a new_chat."""
|
|
21
|
+
source: str = Field(..., pattern=r"com\.chatty/clients/[a-zA-Z0-9-]+")
|
|
22
|
+
|
|
23
|
+
@property
|
|
24
|
+
def client_id(self) -> str:
|
|
25
|
+
match = re.search(r"com\.chatty/clients/([a-zA-Z0-9-]+)", self.source)
|
|
26
|
+
if match:
|
|
27
|
+
return match.group(1)
|
|
28
|
+
raise ValueError("Invalid source format")
|
|
29
|
+
|
|
30
|
+
class InternalEvent(ChattyCloudEvent):
|
|
31
|
+
"""Used for internal events such as a new client, some billing, etc."""
|
|
32
|
+
source: str = Field(..., pattern=r"com\.chatty/internal/[a-z-]+")
|
|
33
|
+
|
|
34
|
+
class BusinessLogicEvent(ClientEvent):
|
|
35
|
+
"""Used for business logic events, such as a quality scoring."""
|
|
36
|
+
source: str = Field(..., pattern=r"com\.chatty/business-logic/[a-zA-Z0-9-]+")
|
|
37
|
+
|
|
38
|
+
class BusinessLogicEventData(BaseModel):
|
|
39
|
+
channel_id : str
|
|
40
|
+
chat_id : StrObjectId
|
|
41
|
+
client_channel_user_id : str = Field(..., alias="waid")
|
|
42
|
+
company_phone_number_id : str
|
|
43
|
+
subtype : StrEnum
|
|
44
|
+
|
|
45
|
+
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
from .base import BusinessLogicEventData, BusinessLogicEvent
|
|
2
|
+
from .event_types import EventType
|
|
3
|
+
from ..utils.types.identifier import StrObjectId
|
|
4
|
+
from enum import StrEnum
|
|
5
|
+
|
|
6
|
+
class CPSubtype(StrEnum):
|
|
7
|
+
CREATED = "created"
|
|
8
|
+
UPDATED = "updated"
|
|
9
|
+
DELETED = "deleted"
|
|
10
|
+
|
|
11
|
+
class ContactPointData(BusinessLogicEventData):
|
|
12
|
+
source_id: StrObjectId
|
|
13
|
+
new_chat : bool
|
|
14
|
+
|
|
15
|
+
class ContactPointEvent(BusinessLogicEvent):
|
|
16
|
+
"""Used for client related events, such as a new chat, a touchpoint, etc."""
|
|
17
|
+
type: EventType = EventType.CONTACT_POINT
|
|
18
|
+
data: ContactPointData
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
from .base import BusinessLogicEventData, BusinessLogicEvent
|
|
2
|
+
from .event_types import EventType
|
|
3
|
+
from enum import StrEnum
|
|
4
|
+
|
|
5
|
+
class NewChatData(BusinessLogicEventData):
|
|
6
|
+
is_inbound : bool
|
|
7
|
+
|
|
8
|
+
class NewChatEvent(BusinessLogicEvent):
|
|
9
|
+
"""Used for client related events, such as a new chat, a touchpoint, etc."""
|
|
10
|
+
type: EventType = EventType.NEW_CHAT
|
|
11
|
+
data: NewChatData
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
from .base import BusinessLogicEventData, BusinessLogicEvent
|
|
2
|
+
from .event_types import EventType
|
|
3
|
+
from enum import StrEnum
|
|
4
|
+
|
|
5
|
+
class QualityScore(StrEnum):
|
|
6
|
+
BAD = "bad"
|
|
7
|
+
GOOD = "good"
|
|
8
|
+
NEUTRAL = "neutral"
|
|
9
|
+
|
|
10
|
+
class QualityScoringData(BusinessLogicEventData):
|
|
11
|
+
score : QualityScore
|
|
12
|
+
|
|
13
|
+
class QualityScoringEvent(BusinessLogicEvent):
|
|
14
|
+
"""Used for client related events, such as a new chat, a touchpoint, etc."""
|
|
15
|
+
type: EventType = EventType.QUALITY_SCORING
|
|
16
|
+
data: QualityScoringData
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
from .base import BusinessLogicEventData, BusinessLogicEvent
|
|
2
|
+
from .event_types import EventType
|
|
3
|
+
from enum import StrEnum
|
|
4
|
+
|
|
5
|
+
class SaleSubtype(StrEnum):
|
|
6
|
+
CREATED = "created"
|
|
7
|
+
UPDATED = "updated"
|
|
8
|
+
DELETED = "deleted"
|
|
9
|
+
|
|
10
|
+
class SaleData(BusinessLogicEventData):
|
|
11
|
+
sale_id: str
|
|
12
|
+
|
|
13
|
+
class SaleEvent(BusinessLogicEvent):
|
|
14
|
+
"""Used for client related events, such as a new chat, a touchpoint, etc."""
|
|
15
|
+
type: EventType = EventType.SALE
|
|
16
|
+
data: SaleData
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from .base import BusinessLogicEventData, BusinessLogicEvent
|
|
2
|
+
from .event_types import EventType
|
|
3
|
+
from enum import StrEnum
|
|
4
|
+
|
|
5
|
+
class TemplateSubtype(StrEnum):
|
|
6
|
+
WAITING = "waiting"
|
|
7
|
+
SENT = "sent"
|
|
8
|
+
DELIVERED = "delivered"
|
|
9
|
+
FAILED = "failed"
|
|
10
|
+
READ = "read"
|
|
11
|
+
|
|
12
|
+
class TemplateData(BusinessLogicEventData):
|
|
13
|
+
message_id: str
|
|
14
|
+
template_name: str
|
|
15
|
+
|
|
16
|
+
class TemplateEvent(BusinessLogicEvent):
|
|
17
|
+
"""Used for client related events, such as a new chat, a touchpoint, etc."""
|
|
18
|
+
type: EventType = EventType.TEMPLATE
|
|
19
|
+
data: TemplateData
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
from typing import Union, TypeAlias
|
|
2
|
+
from .audio import AudioMessage
|
|
3
|
+
from .document import DocumentMessage
|
|
4
|
+
from .image import ImageMessage
|
|
5
|
+
from .location import LocationMessage
|
|
6
|
+
from .sticker import StickerMessage
|
|
7
|
+
from .text import TextMessage
|
|
8
|
+
from .video import VideoMessage
|
|
9
|
+
from .unsupported import UnsupportedMessage
|
|
10
|
+
from .reaction import ReactionMessage
|
|
11
|
+
from .central_notification import CentralNotification
|
|
12
|
+
from .contact import ContactMessage
|
|
13
|
+
from .base import ChattyMessageJson
|
|
14
|
+
# from .button import ButtonMessage
|
|
15
|
+
|
|
16
|
+
ChattyMessage : TypeAlias = Union[AudioMessage, DocumentMessage, ImageMessage, LocationMessage, StickerMessage, TextMessage, VideoMessage, UnsupportedMessage, ReactionMessage, CentralNotification, ContactMessage]
|
|
17
|
+
ChattyMediaMessage : TypeAlias = Union[AudioMessage, ImageMessage, VideoMessage, StickerMessage, DocumentMessage]
|
|
Binary file
|
letschatty-0.1.44/src/letschatty/models/messages/chatty_messages/__pycache__/audio.cpython-311.pyc
ADDED
|
Binary file
|
letschatty-0.1.44/src/letschatty/models/messages/chatty_messages/__pycache__/button.cpython-311.pyc
ADDED
|
Binary file
|
|
Binary file
|
letschatty-0.1.44/src/letschatty/models/messages/chatty_messages/__pycache__/contact.cpython-311.pyc
ADDED
|
Binary file
|
|
Binary file
|
letschatty-0.1.44/src/letschatty/models/messages/chatty_messages/__pycache__/image.cpython-311.pyc
ADDED
|
Binary file
|
|
Binary file
|
|
Binary file
|
letschatty-0.1.44/src/letschatty/models/messages/chatty_messages/__pycache__/sticker.cpython-311.pyc
ADDED
|
Binary file
|
letschatty-0.1.44/src/letschatty/models/messages/chatty_messages/__pycache__/sticket.cpython-311.pyc
ADDED
|
Binary file
|
letschatty-0.1.44/src/letschatty/models/messages/chatty_messages/__pycache__/text.cpython-311.pyc
ADDED
|
Binary file
|
|
Binary file
|
letschatty-0.1.44/src/letschatty/models/messages/chatty_messages/__pycache__/video.cpython-311.pyc
ADDED
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .chatty_message_json import ChattyMessageJson
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
from pydantic import BaseModel, Field
|
|
2
|
+
from typing import Optional, Dict, Any
|
|
3
|
+
from datetime import datetime
|
|
4
|
+
from ....utils.types.message_types import MessageType, MessageSubtype
|
|
5
|
+
from ....utils.types.message_status_types import Status
|
|
6
|
+
|
|
7
|
+
class Content(BaseModel):
|
|
8
|
+
pass
|
|
9
|
+
|
|
10
|
+
class ChattyMessageJson(BaseModel):
|
|
11
|
+
"""This is the database message model"""
|
|
12
|
+
id: str
|
|
13
|
+
created_at: datetime
|
|
14
|
+
updated_at: datetime
|
|
15
|
+
type: MessageType
|
|
16
|
+
status: Status
|
|
17
|
+
is_incoming_message: bool
|
|
18
|
+
content: Dict[str, Any]
|
|
19
|
+
sent_by: Optional[str] = Field(default=None)
|
|
20
|
+
referral: Optional[Dict] = Field(default=None)
|
|
21
|
+
context: Optional[Dict] = Field(default=None)
|
|
22
|
+
subtype: Optional[str] = Field(default="")
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
from pydantic import BaseModel, Field, field_validator, ValidationInfo
|
|
2
|
+
from datetime import datetime, timezone
|
|
3
|
+
from zoneinfo import ZoneInfo, ZoneInfoNotFoundError
|
|
4
|
+
from typing import Dict, Any, Optional
|
|
5
|
+
|
|
6
|
+
from bson import ObjectId
|
|
7
|
+
from ....utils import MessageType, Status, MessageSubtype
|
|
8
|
+
from ..schema import ChattyContent, ChattyContext, ChattyReferral
|
|
9
|
+
|
|
10
|
+
class Message(BaseModel):
|
|
11
|
+
created_at: datetime
|
|
12
|
+
updated_at: datetime
|
|
13
|
+
type: MessageType
|
|
14
|
+
content: ChattyContent
|
|
15
|
+
status: Status
|
|
16
|
+
is_incoming_message: bool
|
|
17
|
+
id: str = Field(default_factory=lambda: str(ObjectId()),description="Unique identifier for the message. In case it's a central notification or a message request (still not confirmed by external API) we'll use an object id as default. Also known as wamid form Meta")
|
|
18
|
+
sent_by: Optional[str] = Field(description="Email of the agent who sent the message. If it's incoming, it'll be None")
|
|
19
|
+
starred: bool = Field(default=False)
|
|
20
|
+
subtype: MessageSubtype = Field(default_factory=lambda: MessageSubtype.NONE)
|
|
21
|
+
referral: ChattyReferral = Field(default_factory=lambda: ChattyReferral.default())
|
|
22
|
+
context: ChattyContext = Field(default_factory=lambda: ChattyContext.default())
|
|
23
|
+
|
|
24
|
+
def model_dump(self, *args, **kwargs) -> Dict[str, Any]:
|
|
25
|
+
"""
|
|
26
|
+
Dump the message to a dictionary, with the option to convert datetimes to a specific timezone.
|
|
27
|
+
"""
|
|
28
|
+
timezone = kwargs.pop('timezone', None)
|
|
29
|
+
data = super().model_dump(*args, **kwargs)
|
|
30
|
+
if timezone:
|
|
31
|
+
try:
|
|
32
|
+
tz = ZoneInfo(timezone)
|
|
33
|
+
data['created_at'] = self.created_at.astimezone(tz).isoformat()
|
|
34
|
+
data['updated_at'] = self.updated_at.astimezone(tz).isoformat()
|
|
35
|
+
except ZoneInfoNotFoundError:
|
|
36
|
+
raise ValueError(f"Invalid timezone: {timezone}")
|
|
37
|
+
return data
|
|
38
|
+
|
|
39
|
+
class ConfigDict:
|
|
40
|
+
validate_assignment = True
|
|
41
|
+
|
|
42
|
+
@field_validator('sent_by', mode='before')
|
|
43
|
+
def validate_sent_by(cls, v: Optional[str], info: ValidationInfo) -> Optional[str]:
|
|
44
|
+
"""Ensure that the sent_by field is not required for incoming messages, and that it's a valid email for outgoing messages."""
|
|
45
|
+
is_incoming = info.data.get('is_incoming_message', False)
|
|
46
|
+
if is_incoming:
|
|
47
|
+
return None
|
|
48
|
+
if not is_incoming and not v:
|
|
49
|
+
raise ValueError("sent_by is required for outgoing messages")
|
|
50
|
+
return v
|
|
51
|
+
|
|
52
|
+
@field_validator('status', mode='before')
|
|
53
|
+
def validate_status(cls, v: Optional[str], info: ValidationInfo) -> Status:
|
|
54
|
+
"""Status should be validated always, both instantiation and assignment"""
|
|
55
|
+
if isinstance(v, str):
|
|
56
|
+
return Status(v)
|
|
57
|
+
return v
|
|
58
|
+
|
|
59
|
+
@field_validator('subtype', mode='before')
|
|
60
|
+
def validate_subtype(cls, v: Optional[str], info: ValidationInfo) -> MessageSubtype:
|
|
61
|
+
"""If there's no subtype, we'll use the subtype NONE."""
|
|
62
|
+
if v is None or v == "":
|
|
63
|
+
return MessageSubtype.NONE
|
|
64
|
+
return v
|
|
65
|
+
|
|
66
|
+
@field_validator('referral', mode='before')
|
|
67
|
+
def validate_referral(cls, v: Optional[Dict], info: ValidationInfo) -> ChattyReferral:
|
|
68
|
+
"""If there's no referral, we'll use the referral default."""
|
|
69
|
+
if v is None or v == {}:
|
|
70
|
+
return ChattyReferral.default()
|
|
71
|
+
return v
|
|
72
|
+
|
|
73
|
+
@field_validator('context', mode='before')
|
|
74
|
+
def validate_context(cls, v: Optional[Dict], info: ValidationInfo) -> ChattyContext:
|
|
75
|
+
"""If there's no context, we'll use the context default."""
|
|
76
|
+
if v is None or v == {}:
|
|
77
|
+
return ChattyContext.default()
|
|
78
|
+
return v
|
|
79
|
+
|
|
80
|
+
@field_validator('context', mode='after')
|
|
81
|
+
def validate_context_based_on_subtype(cls, v: ChattyContext, info: ValidationInfo) -> ChattyContext:
|
|
82
|
+
"""We'll validate the context based on the subtype.
|
|
83
|
+
And if there's no context, we'll use the context default."""
|
|
84
|
+
subtype = info.data.get('subtype')
|
|
85
|
+
if subtype == MessageSubtype.TEMPLATE:
|
|
86
|
+
if v.template_name is None:
|
|
87
|
+
raise ValueError("template_name is required for template messages")
|
|
88
|
+
elif subtype == MessageSubtype.CHATTY_RESPONSE:
|
|
89
|
+
if v.response_id is None:
|
|
90
|
+
raise ValueError("response_id is required for chatty_response messages")
|
|
91
|
+
return v
|
|
92
|
+
|
|
93
|
+
@field_validator('created_at', 'updated_at')
|
|
94
|
+
def ensure_utc(cls, v):
|
|
95
|
+
if isinstance(v, datetime):
|
|
96
|
+
return v.replace(tzinfo=timezone.utc) if v.tzinfo is None else v.astimezone(timezone.utc)
|
|
97
|
+
raise ValueError('must be a datetime')
|
|
98
|
+
|
|
99
|
+
def _update_status(self, new_status: Status):
|
|
100
|
+
self.status = new_status
|
|
101
|
+
self.updated_at = datetime.now(timezone.utc)
|
|
102
|
+
|
|
103
|
+
def mark_as_read(self):
|
|
104
|
+
"""Mark the message as read if not already failed."""
|
|
105
|
+
self._update_status(Status.READ)
|
|
106
|
+
|
|
107
|
+
def mark_as_delivered(self):
|
|
108
|
+
"""Mark the message as delivered if it was sent."""
|
|
109
|
+
self._update_status(Status.DELIVERED)
|
|
110
|
+
|
|
111
|
+
def mark_as_failed(self):
|
|
112
|
+
"""Mark the message as failed."""
|
|
113
|
+
self._update_status(Status.FAILED)
|
|
114
|
+
|
|
115
|
+
def mark_as_sent(self):
|
|
116
|
+
"""Mark the message as sent."""
|
|
117
|
+
self._update_status(Status.SENT)
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
from typing import TypeAlias, Union
|
|
2
|
+
from .chatty_content.content_image import ChattyContentImage
|
|
3
|
+
from .chatty_content.content_text import ChattyContentText
|
|
4
|
+
from .chatty_content.content_video import ChattyContentVideo
|
|
5
|
+
from .chatty_content.content_audio import ChattyContentAudio
|
|
6
|
+
from .chatty_content.content_reaction import ChattyContentReaction
|
|
7
|
+
from .chatty_content.content_location import ChattyContentLocation
|
|
8
|
+
from .chatty_content.content_contacts import ChattyContentContacts
|
|
9
|
+
from .chatty_content.content_document import ChattyContentDocument
|
|
10
|
+
from .chatty_content.content_sticker import ChattyContentSticker
|
|
11
|
+
from .chatty_content.content_central import ChattyContentCentral
|
|
12
|
+
|
|
13
|
+
from .chatty_context.chatty_context import ChattyContext
|
|
14
|
+
from .chatty_referal.chatty_referal import ChattyReferral
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
ChattyContent : TypeAlias = Union[ChattyContentImage, ChattyContentText, ChattyContentVideo, ChattyContentAudio, ChattyContentReaction, ChattyContentLocation, ChattyContentContacts, ChattyContentDocument, ChattyContentSticker, ChattyContentCentral]
|
|
18
|
+
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|