chatgraph 1.2.3__tar.gz → 1.2.5__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.
- {chatgraph-1.2.3 → chatgraph-1.2.5}/PKG-INFO +1 -1
- {chatgraph-1.2.3 → chatgraph-1.2.5}/chatgraph/__init__.py +4 -1
- {chatgraph-1.2.3 → chatgraph-1.2.5}/chatgraph/logger/__init__.py +11 -11
- {chatgraph-1.2.3 → chatgraph-1.2.5}/chatgraph/logger/user_logger.py +88 -88
- {chatgraph-1.2.3 → chatgraph-1.2.5}/chatgraph/messages/message_consumer.py +26 -6
- chatgraph-1.2.5/chatgraph/models/platform_state.py +35 -0
- {chatgraph-1.2.3 → chatgraph-1.2.5}/chatgraph/services/router_http_client.py +8 -3
- {chatgraph-1.2.3 → chatgraph-1.2.5}/chatgraph/types/usercall.py +22 -8
- {chatgraph-1.2.3 → chatgraph-1.2.5}/docs/gaps-go-to-python.md +150 -150
- {chatgraph-1.2.3 → chatgraph-1.2.5}/docs/gaps-python-to-go.md +65 -65
- {chatgraph-1.2.3 → chatgraph-1.2.5}/example2.py +59 -59
- {chatgraph-1.2.3 → chatgraph-1.2.5}/pyproject.toml +1 -1
- {chatgraph-1.2.3 → chatgraph-1.2.5}/tests/unit/test_default_guard.py +93 -92
- {chatgraph-1.2.3 → chatgraph-1.2.5}/tests/unit/test_message_consumer.py +403 -364
- chatgraph-1.2.5/tests/unit/test_models_platform_state.py +52 -0
- {chatgraph-1.2.3 → chatgraph-1.2.5}/tests/unit/test_router_http_client.py +105 -14
- {chatgraph-1.2.3 → chatgraph-1.2.5}/tests/unit/test_user_logger.py +146 -146
- {chatgraph-1.2.3 → chatgraph-1.2.5}/tests/unit/test_usercall.py +436 -400
- {chatgraph-1.2.3 → chatgraph-1.2.5}/.env.example +0 -0
- {chatgraph-1.2.3 → chatgraph-1.2.5}/.github/agents/SkillManager.agent.md +0 -0
- {chatgraph-1.2.3 → chatgraph-1.2.5}/.github/agents/architect.agent.md +0 -0
- {chatgraph-1.2.3 → chatgraph-1.2.5}/.github/agents/code-reviewer.agent.md +0 -0
- {chatgraph-1.2.3 → chatgraph-1.2.5}/.github/agents/developer.agent.md +0 -0
- {chatgraph-1.2.3 → chatgraph-1.2.5}/.github/copilot-instructions.md +0 -0
- {chatgraph-1.2.3 → chatgraph-1.2.5}/.github/skills/chatgraph-framework/SKILL.md +0 -0
- {chatgraph-1.2.3 → chatgraph-1.2.5}/.gitignore +0 -0
- {chatgraph-1.2.3 → chatgraph-1.2.5}/.python-version +0 -0
- {chatgraph-1.2.3 → chatgraph-1.2.5}/LICENSE +0 -0
- {chatgraph-1.2.3 → chatgraph-1.2.5}/README.md +0 -0
- {chatgraph-1.2.3 → chatgraph-1.2.5}/chatgraph/auth/credentials.py +0 -0
- {chatgraph-1.2.3 → chatgraph-1.2.5}/chatgraph/bot/chatbot_model.py +0 -0
- {chatgraph-1.2.3 → chatgraph-1.2.5}/chatgraph/bot/chatbot_router.py +0 -0
- {chatgraph-1.2.3 → chatgraph-1.2.5}/chatgraph/bot/default_functions.py +0 -0
- {chatgraph-1.2.3 → chatgraph-1.2.5}/chatgraph/bot/default_guard.py +0 -0
- {chatgraph-1.2.3 → chatgraph-1.2.5}/chatgraph/cli/__init__.py +0 -0
- {chatgraph-1.2.3 → chatgraph-1.2.5}/chatgraph/container/container.py +0 -0
- {chatgraph-1.2.3 → chatgraph-1.2.5}/chatgraph/error/chatbot_error.py +0 -0
- {chatgraph-1.2.3 → chatgraph-1.2.5}/chatgraph/error/route_error.py +0 -0
- {chatgraph-1.2.3 → chatgraph-1.2.5}/chatgraph/gRPC/gRPCCall.py +0 -0
- {chatgraph-1.2.3 → chatgraph-1.2.5}/chatgraph/logger/logger.py +0 -0
- {chatgraph-1.2.3 → chatgraph-1.2.5}/chatgraph/models/actions.py +0 -0
- {chatgraph-1.2.3 → chatgraph-1.2.5}/chatgraph/models/http_responses.py +0 -0
- {chatgraph-1.2.3 → chatgraph-1.2.5}/chatgraph/models/message.py +0 -0
- {chatgraph-1.2.3 → chatgraph-1.2.5}/chatgraph/models/userstate.py +0 -0
- {chatgraph-1.2.3 → chatgraph-1.2.5}/chatgraph/pb/router.proto +0 -0
- {chatgraph-1.2.3 → chatgraph-1.2.5}/chatgraph/pb/router_pb2.py +0 -0
- {chatgraph-1.2.3 → chatgraph-1.2.5}/chatgraph/pb/router_pb2_grpc.py +0 -0
- {chatgraph-1.2.3 → chatgraph-1.2.5}/chatgraph/services/__init__.py +0 -0
- {chatgraph-1.2.3 → chatgraph-1.2.5}/chatgraph/types/background_task.py +0 -0
- {chatgraph-1.2.3 → chatgraph-1.2.5}/chatgraph/types/end_types.py +0 -0
- {chatgraph-1.2.3 → chatgraph-1.2.5}/chatgraph/types/route.py +0 -0
- {chatgraph-1.2.3 → chatgraph-1.2.5}/example.py +0 -0
- {chatgraph-1.2.3 → chatgraph-1.2.5}/jsons/voll_return.json +0 -0
- {chatgraph-1.2.3 → chatgraph-1.2.5}/poetry.lock +0 -0
- {chatgraph-1.2.3 → chatgraph-1.2.5}/tests/__init__.py +0 -0
- {chatgraph-1.2.3 → chatgraph-1.2.5}/tests/integration/__init__.py +0 -0
- {chatgraph-1.2.3 → chatgraph-1.2.5}/tests/integration/conftest.py +0 -0
- {chatgraph-1.2.3 → chatgraph-1.2.5}/tests/integration/test_router_client_integration.py +0 -0
- {chatgraph-1.2.3 → chatgraph-1.2.5}/tests/unit/__init__.py +0 -0
- {chatgraph-1.2.3 → chatgraph-1.2.5}/tests/unit/conftest.py +0 -0
- {chatgraph-1.2.3 → chatgraph-1.2.5}/tests/unit/test_guard.py +0 -0
- {chatgraph-1.2.3 → chatgraph-1.2.5}/tests/unit/test_models_actions.py +0 -0
- {chatgraph-1.2.3 → chatgraph-1.2.5}/tests/unit/test_models_message.py +0 -0
- {chatgraph-1.2.3 → chatgraph-1.2.5}/tests/unit/test_models_userstate.py +0 -0
- {chatgraph-1.2.3 → chatgraph-1.2.5}/uv.lock +0 -0
|
@@ -6,15 +6,16 @@ from .container.container import Container
|
|
|
6
6
|
from .logger import logger, set_level
|
|
7
7
|
from .messages.message_consumer import MessageConsumer
|
|
8
8
|
from .models.message import Button, File, Message, SendType, TextMessage
|
|
9
|
+
from .models.platform_state import PlatformState, VollStateData
|
|
9
10
|
from .models.userstate import (
|
|
10
11
|
AuthLevel,
|
|
11
12
|
ChatID,
|
|
12
13
|
Menu,
|
|
14
|
+
User,
|
|
13
15
|
UserData,
|
|
14
16
|
UserIdentity,
|
|
15
17
|
UserInternal,
|
|
16
18
|
UserState,
|
|
17
|
-
User,
|
|
18
19
|
)
|
|
19
20
|
from .types.background_task import BackgroundTask
|
|
20
21
|
from .types.end_types import (
|
|
@@ -54,4 +55,6 @@ __all__ = [
|
|
|
54
55
|
"BackgroundTask",
|
|
55
56
|
"Container", "logger",
|
|
56
57
|
"default_guard",
|
|
58
|
+
"PlatformState",
|
|
59
|
+
"VollStateData",
|
|
57
60
|
]
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import logging
|
|
2
|
-
|
|
3
|
-
from .user_logger import UserLoggerManager
|
|
4
|
-
|
|
5
|
-
logger_httpx = logging.getLogger('httpx')
|
|
6
|
-
logger_httpx.setLevel(logging.ERROR)
|
|
7
|
-
|
|
8
|
-
get_system_logger = UserLoggerManager.get_system_logger
|
|
9
|
-
get_user_logger = UserLoggerManager.get_user_logger
|
|
10
|
-
set_level = UserLoggerManager.set_level
|
|
11
|
-
remove_user_logger = UserLoggerManager.remove_user_logger
|
|
1
|
+
import logging
|
|
2
|
+
|
|
3
|
+
from .user_logger import UserLoggerManager
|
|
4
|
+
|
|
5
|
+
logger_httpx = logging.getLogger('httpx')
|
|
6
|
+
logger_httpx.setLevel(logging.ERROR)
|
|
7
|
+
|
|
8
|
+
get_system_logger = UserLoggerManager.get_system_logger
|
|
9
|
+
get_user_logger = UserLoggerManager.get_user_logger
|
|
10
|
+
set_level = UserLoggerManager.set_level
|
|
11
|
+
remove_user_logger = UserLoggerManager.remove_user_logger
|
|
@@ -1,88 +1,88 @@
|
|
|
1
|
-
import logging
|
|
2
|
-
import os
|
|
3
|
-
import sys
|
|
4
|
-
|
|
5
|
-
LOG_DIR = "chatgraph_logs"
|
|
6
|
-
LOG_FORMAT = "%(asctime)s | %(levelname)s | %(message)s | %(funcName)s | %(name)s"
|
|
7
|
-
|
|
8
|
-
_ENV_LEVEL = os.getenv("CHATGRAPH_LOG_LEVEL", "").upper()
|
|
9
|
-
_DEFAULT_LEVEL: int = getattr(logging, _ENV_LEVEL, logging.INFO)
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
class UserLoggerManager:
|
|
13
|
-
_loggers: dict[str, logging.Logger] = {}
|
|
14
|
-
_level: int = _DEFAULT_LEVEL
|
|
15
|
-
|
|
16
|
-
@classmethod
|
|
17
|
-
def set_level(cls, level: int | str) -> None:
|
|
18
|
-
if isinstance(level, str):
|
|
19
|
-
numeric = getattr(logging, level.upper(), None)
|
|
20
|
-
if numeric is None:
|
|
21
|
-
raise ValueError(f"Nível de log inválido: '{level}'")
|
|
22
|
-
level = numeric
|
|
23
|
-
cls._level = level
|
|
24
|
-
for logger in cls._loggers.values():
|
|
25
|
-
logger.setLevel(level)
|
|
26
|
-
for handler in logger.handlers:
|
|
27
|
-
handler.setLevel(level)
|
|
28
|
-
|
|
29
|
-
@classmethod
|
|
30
|
-
def get_user_logger(cls, user_id: str, company_id: str) -> logging.Logger:
|
|
31
|
-
key = f"{user_id}_{company_id}"
|
|
32
|
-
if key in cls._loggers:
|
|
33
|
-
return cls._loggers[key]
|
|
34
|
-
|
|
35
|
-
os.makedirs(LOG_DIR, exist_ok=True)
|
|
36
|
-
|
|
37
|
-
logger = logging.getLogger(key)
|
|
38
|
-
logger.setLevel(cls._level)
|
|
39
|
-
|
|
40
|
-
if not logger.handlers:
|
|
41
|
-
handler = logging.FileHandler(
|
|
42
|
-
os.path.join(LOG_DIR, f"{key}.log"), encoding="utf-8"
|
|
43
|
-
)
|
|
44
|
-
handler.setLevel(cls._level)
|
|
45
|
-
handler.setFormatter(logging.Formatter(LOG_FORMAT))
|
|
46
|
-
logger.addHandler(handler)
|
|
47
|
-
stream_handler = logging.StreamHandler(sys.stdout)
|
|
48
|
-
stream_handler.setLevel(cls._level)
|
|
49
|
-
stream_handler.setFormatter(logging.Formatter(LOG_FORMAT))
|
|
50
|
-
logger.addHandler(stream_handler)
|
|
51
|
-
|
|
52
|
-
cls._loggers[key] = logger
|
|
53
|
-
return logger
|
|
54
|
-
|
|
55
|
-
@classmethod
|
|
56
|
-
def remove_user_logger(cls, user_id: str, company_id: str) -> None:
|
|
57
|
-
key = f"{user_id}_{company_id}"
|
|
58
|
-
logger = cls._loggers.pop(key, None)
|
|
59
|
-
if logger:
|
|
60
|
-
for handler in logger.handlers[:]:
|
|
61
|
-
handler.close()
|
|
62
|
-
logger.removeHandler(handler)
|
|
63
|
-
|
|
64
|
-
@classmethod
|
|
65
|
-
def get_system_logger(cls) -> logging.Logger:
|
|
66
|
-
key = "chatgraph.system"
|
|
67
|
-
if key in cls._loggers:
|
|
68
|
-
return cls._loggers[key]
|
|
69
|
-
|
|
70
|
-
os.makedirs(LOG_DIR, exist_ok=True)
|
|
71
|
-
|
|
72
|
-
logger = logging.getLogger(key)
|
|
73
|
-
logger.setLevel(cls._level)
|
|
74
|
-
|
|
75
|
-
if not logger.handlers:
|
|
76
|
-
handler = logging.FileHandler(
|
|
77
|
-
os.path.join(LOG_DIR, "system.log"), encoding="utf-8"
|
|
78
|
-
)
|
|
79
|
-
handler.setLevel(cls._level)
|
|
80
|
-
handler.setFormatter(logging.Formatter(LOG_FORMAT))
|
|
81
|
-
logger.addHandler(handler)
|
|
82
|
-
stream_handler = logging.StreamHandler(sys.stdout)
|
|
83
|
-
stream_handler.setLevel(cls._level)
|
|
84
|
-
stream_handler.setFormatter(logging.Formatter(LOG_FORMAT))
|
|
85
|
-
logger.addHandler(stream_handler)
|
|
86
|
-
|
|
87
|
-
cls._loggers[key] = logger
|
|
88
|
-
return logger
|
|
1
|
+
import logging
|
|
2
|
+
import os
|
|
3
|
+
import sys
|
|
4
|
+
|
|
5
|
+
LOG_DIR = "chatgraph_logs"
|
|
6
|
+
LOG_FORMAT = "%(asctime)s | %(levelname)s | %(message)s | %(funcName)s | %(name)s"
|
|
7
|
+
|
|
8
|
+
_ENV_LEVEL = os.getenv("CHATGRAPH_LOG_LEVEL", "").upper()
|
|
9
|
+
_DEFAULT_LEVEL: int = getattr(logging, _ENV_LEVEL, logging.INFO)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class UserLoggerManager:
|
|
13
|
+
_loggers: dict[str, logging.Logger] = {}
|
|
14
|
+
_level: int = _DEFAULT_LEVEL
|
|
15
|
+
|
|
16
|
+
@classmethod
|
|
17
|
+
def set_level(cls, level: int | str) -> None:
|
|
18
|
+
if isinstance(level, str):
|
|
19
|
+
numeric = getattr(logging, level.upper(), None)
|
|
20
|
+
if numeric is None:
|
|
21
|
+
raise ValueError(f"Nível de log inválido: '{level}'")
|
|
22
|
+
level = numeric
|
|
23
|
+
cls._level = level
|
|
24
|
+
for logger in cls._loggers.values():
|
|
25
|
+
logger.setLevel(level)
|
|
26
|
+
for handler in logger.handlers:
|
|
27
|
+
handler.setLevel(level)
|
|
28
|
+
|
|
29
|
+
@classmethod
|
|
30
|
+
def get_user_logger(cls, user_id: str, company_id: str) -> logging.Logger:
|
|
31
|
+
key = f"{user_id}_{company_id}"
|
|
32
|
+
if key in cls._loggers:
|
|
33
|
+
return cls._loggers[key]
|
|
34
|
+
|
|
35
|
+
os.makedirs(LOG_DIR, exist_ok=True)
|
|
36
|
+
|
|
37
|
+
logger = logging.getLogger(key)
|
|
38
|
+
logger.setLevel(cls._level)
|
|
39
|
+
|
|
40
|
+
if not logger.handlers:
|
|
41
|
+
handler = logging.FileHandler(
|
|
42
|
+
os.path.join(LOG_DIR, f"{key}.log"), encoding="utf-8"
|
|
43
|
+
)
|
|
44
|
+
handler.setLevel(cls._level)
|
|
45
|
+
handler.setFormatter(logging.Formatter(LOG_FORMAT))
|
|
46
|
+
logger.addHandler(handler)
|
|
47
|
+
stream_handler = logging.StreamHandler(sys.stdout)
|
|
48
|
+
stream_handler.setLevel(cls._level)
|
|
49
|
+
stream_handler.setFormatter(logging.Formatter(LOG_FORMAT))
|
|
50
|
+
logger.addHandler(stream_handler)
|
|
51
|
+
|
|
52
|
+
cls._loggers[key] = logger
|
|
53
|
+
return logger
|
|
54
|
+
|
|
55
|
+
@classmethod
|
|
56
|
+
def remove_user_logger(cls, user_id: str, company_id: str) -> None:
|
|
57
|
+
key = f"{user_id}_{company_id}"
|
|
58
|
+
logger = cls._loggers.pop(key, None)
|
|
59
|
+
if logger:
|
|
60
|
+
for handler in logger.handlers[:]:
|
|
61
|
+
handler.close()
|
|
62
|
+
logger.removeHandler(handler)
|
|
63
|
+
|
|
64
|
+
@classmethod
|
|
65
|
+
def get_system_logger(cls) -> logging.Logger:
|
|
66
|
+
key = "chatgraph.system"
|
|
67
|
+
if key in cls._loggers:
|
|
68
|
+
return cls._loggers[key]
|
|
69
|
+
|
|
70
|
+
os.makedirs(LOG_DIR, exist_ok=True)
|
|
71
|
+
|
|
72
|
+
logger = logging.getLogger(key)
|
|
73
|
+
logger.setLevel(cls._level)
|
|
74
|
+
|
|
75
|
+
if not logger.handlers:
|
|
76
|
+
handler = logging.FileHandler(
|
|
77
|
+
os.path.join(LOG_DIR, "system.log"), encoding="utf-8"
|
|
78
|
+
)
|
|
79
|
+
handler.setLevel(cls._level)
|
|
80
|
+
handler.setFormatter(logging.Formatter(LOG_FORMAT))
|
|
81
|
+
logger.addHandler(handler)
|
|
82
|
+
stream_handler = logging.StreamHandler(sys.stdout)
|
|
83
|
+
stream_handler.setLevel(cls._level)
|
|
84
|
+
stream_handler.setFormatter(logging.Formatter(LOG_FORMAT))
|
|
85
|
+
logger.addHandler(stream_handler)
|
|
86
|
+
|
|
87
|
+
cls._loggers[key] = logger
|
|
88
|
+
return logger
|
|
@@ -13,6 +13,7 @@ from rich.text import Text
|
|
|
13
13
|
from ..auth.credentials import Credential
|
|
14
14
|
from ..logger.user_logger import UserLoggerManager
|
|
15
15
|
from ..models.message import Message
|
|
16
|
+
from ..models.platform_state import PlatformState
|
|
16
17
|
from ..models.userstate import UserState
|
|
17
18
|
from ..services.router_http_client import RouterHTTPClient
|
|
18
19
|
from ..types.usercall import UserCall
|
|
@@ -32,6 +33,8 @@ class MessageConsumer:
|
|
|
32
33
|
virtual_host: str = '/',
|
|
33
34
|
heartbeat: int = 60,
|
|
34
35
|
reconnect_interval: float = 5.0,
|
|
36
|
+
x_expires: int = 86400000,
|
|
37
|
+
x_message_ttl: int = 3600000,
|
|
35
38
|
) -> None:
|
|
36
39
|
if heartbeat < 0:
|
|
37
40
|
raise ValueError('heartbeat must be >= 0')
|
|
@@ -39,6 +42,8 @@ class MessageConsumer:
|
|
|
39
42
|
raise ValueError('reconnect_interval must be >= 0')
|
|
40
43
|
self.__virtual_host = virtual_host
|
|
41
44
|
self.__prefetch_count = prefetch_count
|
|
45
|
+
self.__x_expires = x_expires
|
|
46
|
+
self.__x_message_ttl = x_message_ttl
|
|
42
47
|
self.__queue_consume = queue_consume
|
|
43
48
|
self.__amqp_url = amqp_url
|
|
44
49
|
self.__router_url = router_url
|
|
@@ -61,6 +66,8 @@ class MessageConsumer:
|
|
|
61
66
|
router_token_env: str = 'ROUTER_TOKEN',
|
|
62
67
|
heartbeat_env: str = 'RABBIT_HEARTBEAT',
|
|
63
68
|
reconnect_interval_env: str = 'RABBIT_RECONNECT_INTERVAL',
|
|
69
|
+
x_expires_env: str = 'RABBIT_X_EXPIRES',
|
|
70
|
+
x_message_ttl_env: str = 'RABBIT_X_MESSAGE_TTL',
|
|
64
71
|
) -> 'MessageConsumer':
|
|
65
72
|
username = os.getenv(user_env)
|
|
66
73
|
password = os.getenv(pass_env)
|
|
@@ -72,6 +79,8 @@ class MessageConsumer:
|
|
|
72
79
|
router_token = os.getenv(router_token_env)
|
|
73
80
|
heartbeat = os.getenv(heartbeat_env, '60')
|
|
74
81
|
reconnect_interval = os.getenv(reconnect_interval_env, '5.0')
|
|
82
|
+
x_expires = os.getenv(x_expires_env, '86400000')
|
|
83
|
+
x_message_ttl = os.getenv(x_message_ttl_env, '3600000')
|
|
75
84
|
|
|
76
85
|
envs_essentials = {
|
|
77
86
|
username: user_env,
|
|
@@ -98,6 +107,8 @@ class MessageConsumer:
|
|
|
98
107
|
router_token=router_token,
|
|
99
108
|
heartbeat=int(heartbeat),
|
|
100
109
|
reconnect_interval=float(reconnect_interval),
|
|
110
|
+
x_expires=int(x_expires),
|
|
111
|
+
x_message_ttl=int(x_message_ttl),
|
|
101
112
|
)
|
|
102
113
|
|
|
103
114
|
async def __initialize_router(self) -> RouterHTTPClient:
|
|
@@ -119,8 +130,8 @@ class MessageConsumer:
|
|
|
119
130
|
async def __declare_queue(self, channel) -> aio_pika.abc.AbstractQueue:
|
|
120
131
|
arguments = {
|
|
121
132
|
'x-dead-letter-exchange': 'log_error',
|
|
122
|
-
'x-expires':
|
|
123
|
-
'x-message-ttl':
|
|
133
|
+
'x-expires': self.__x_expires,
|
|
134
|
+
'x-message-ttl': self.__x_message_ttl,
|
|
124
135
|
}
|
|
125
136
|
queue = await channel.declare_queue(
|
|
126
137
|
self.__queue_consume,
|
|
@@ -144,7 +155,9 @@ class MessageConsumer:
|
|
|
144
155
|
channel = await connection.channel()
|
|
145
156
|
await channel.set_qos(prefetch_count=self.__prefetch_count)
|
|
146
157
|
queue = await self.__declare_queue(channel)
|
|
147
|
-
_logger.info(
|
|
158
|
+
_logger.info(
|
|
159
|
+
'[x] Server inicializado! Aguardando solicitações RPC'
|
|
160
|
+
)
|
|
148
161
|
async for message in queue:
|
|
149
162
|
async with message.process():
|
|
150
163
|
await self.on_request(message.body, process_message)
|
|
@@ -178,12 +191,14 @@ class MessageConsumer:
|
|
|
178
191
|
_logger.error(f'Erro ao processar mensagem: {e}')
|
|
179
192
|
finally:
|
|
180
193
|
if pure_message is not None:
|
|
181
|
-
UserLoggerManager.remove_user_logger(
|
|
194
|
+
UserLoggerManager.remove_user_logger(
|
|
195
|
+
pure_message.user_id, pure_message.company_id
|
|
196
|
+
)
|
|
182
197
|
|
|
183
198
|
async def __transform_message(self, message: dict) -> UserCall:
|
|
184
199
|
user_state = message.get('user_state', {})
|
|
185
200
|
message_data = message.get('message', {})
|
|
186
|
-
observation = user_state.get('observation',
|
|
201
|
+
observation = user_state.get('observation', '{}')
|
|
187
202
|
|
|
188
203
|
if isinstance(observation, str):
|
|
189
204
|
observation = json.loads(observation)
|
|
@@ -191,13 +206,18 @@ class MessageConsumer:
|
|
|
191
206
|
user_state_models = UserState.from_dict(user_state)
|
|
192
207
|
message_models = Message.from_dict(message_data)
|
|
193
208
|
|
|
194
|
-
|
|
209
|
+
platform_state_data = message.get('platform_state', {})
|
|
210
|
+
if not isinstance(platform_state_data, dict):
|
|
211
|
+
platform_state_data = None
|
|
212
|
+
platform_state = PlatformState.from_dict(platform_state_data)
|
|
213
|
+
|
|
195
214
|
router_client = await self.__initialize_router()
|
|
196
215
|
|
|
197
216
|
usercall = UserCall(
|
|
198
217
|
user_state=user_state_models,
|
|
199
218
|
message=message_models,
|
|
200
219
|
router_client=router_client,
|
|
220
|
+
platform_state=platform_state,
|
|
201
221
|
)
|
|
202
222
|
|
|
203
223
|
return usercall
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
from dataclasses import dataclass, field
|
|
2
|
+
from typing import Optional
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
@dataclass
|
|
6
|
+
class PlatformState:
|
|
7
|
+
data: dict = field(default_factory=dict)
|
|
8
|
+
|
|
9
|
+
def to_dict(self) -> dict:
|
|
10
|
+
return self.data
|
|
11
|
+
|
|
12
|
+
@classmethod
|
|
13
|
+
def from_dict(cls, data: Optional[dict]) -> 'PlatformState':
|
|
14
|
+
if data is None:
|
|
15
|
+
return cls(data={})
|
|
16
|
+
return cls(data=data)
|
|
17
|
+
|
|
18
|
+
@property
|
|
19
|
+
def as_voll(self) -> Optional['VollStateData']:
|
|
20
|
+
try:
|
|
21
|
+
return VollStateData(**self.data)
|
|
22
|
+
except (TypeError, ValueError):
|
|
23
|
+
return None
|
|
24
|
+
|
|
25
|
+
def __bool__(self) -> bool:
|
|
26
|
+
return bool(self.data)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@dataclass
|
|
30
|
+
class VollStateData:
|
|
31
|
+
session_id: int
|
|
32
|
+
customer_id: str
|
|
33
|
+
platform: str
|
|
34
|
+
protocol: str
|
|
35
|
+
campaign: str
|
|
@@ -3,10 +3,11 @@ from typing import Any, Dict, Optional
|
|
|
3
3
|
import httpx
|
|
4
4
|
|
|
5
5
|
from ..logger.user_logger import UserLoggerManager
|
|
6
|
-
from ..models.http_responses import RouterResponses
|
|
7
|
-
from ..models.userstate import UserState, ChatID, Menu, User, UserIdentity
|
|
8
|
-
from ..models.message import Message, File
|
|
9
6
|
from ..models.actions import EndAction
|
|
7
|
+
from ..models.http_responses import RouterResponses
|
|
8
|
+
from ..models.message import File, Message
|
|
9
|
+
from ..models.platform_state import PlatformState
|
|
10
|
+
from ..models.userstate import ChatID, Menu, User, UserIdentity, UserState
|
|
10
11
|
|
|
11
12
|
_logger = UserLoggerManager.get_system_logger()
|
|
12
13
|
|
|
@@ -258,6 +259,7 @@ class RouterHTTPClient:
|
|
|
258
259
|
self,
|
|
259
260
|
message_data: Message,
|
|
260
261
|
user_state: UserState,
|
|
262
|
+
platform_state: PlatformState = PlatformState(),
|
|
261
263
|
) -> Any:
|
|
262
264
|
"""
|
|
263
265
|
Envia uma mensagem de texto ao usuário.
|
|
@@ -267,6 +269,7 @@ class RouterHTTPClient:
|
|
|
267
269
|
- chat_id: ID do chat (user_id, company_id)
|
|
268
270
|
- type: Tipo da mensagem
|
|
269
271
|
- detail: Conteúdo da mensagem
|
|
272
|
+
platform_state: Estado específico da plataforma (opcional).
|
|
270
273
|
|
|
271
274
|
Returns:
|
|
272
275
|
Objeto de resposta com atributo 'status' indicando sucesso/falha.
|
|
@@ -280,6 +283,8 @@ class RouterHTTPClient:
|
|
|
280
283
|
'message': message_data.to_dict(),
|
|
281
284
|
'user_state': user_state.to_dict(),
|
|
282
285
|
}
|
|
286
|
+
if platform_state:
|
|
287
|
+
payload['platform_state'] = platform_state.to_dict()
|
|
283
288
|
_logger.debug(f"[send_message] POST {endpoint}")
|
|
284
289
|
response = await self._actions_client.post(
|
|
285
290
|
endpoint,
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import asyncio
|
|
2
|
-
import concurrent.futures
|
|
3
2
|
import json
|
|
4
3
|
import logging
|
|
5
4
|
from typing import Optional
|
|
@@ -10,6 +9,7 @@ from chatgraph.models.message import (
|
|
|
10
9
|
Message,
|
|
11
10
|
MessageTypes,
|
|
12
11
|
)
|
|
12
|
+
from chatgraph.models.platform_state import PlatformState
|
|
13
13
|
from chatgraph.models.userstate import Menu, User, UserIdentity, UserState
|
|
14
14
|
from chatgraph.services.router_http_client import RouterHTTPClient
|
|
15
15
|
|
|
@@ -33,11 +33,13 @@ class UserCall: # noqa: PLR0904
|
|
|
33
33
|
user_state: UserState,
|
|
34
34
|
message: Message,
|
|
35
35
|
router_client: RouterHTTPClient,
|
|
36
|
+
platform_state: PlatformState = PlatformState(),
|
|
36
37
|
) -> None:
|
|
37
38
|
self.type = type
|
|
38
39
|
self.__message = message
|
|
39
40
|
self.__user_state = user_state
|
|
40
41
|
self.__router_client = router_client
|
|
42
|
+
self.__platform_state = platform_state
|
|
41
43
|
self.__content_message = self.__message.text_message.detail
|
|
42
44
|
|
|
43
45
|
@property
|
|
@@ -115,21 +117,23 @@ class UserCall: # noqa: PLR0904
|
|
|
115
117
|
|
|
116
118
|
async def __send(self, message: Message) -> None:
|
|
117
119
|
try:
|
|
118
|
-
self.logger.
|
|
120
|
+
self.logger.info(
|
|
119
121
|
f'Enviando mensagem | user={self.user_id} | company={self.company_id} | tipo={message.type if hasattr(message, "type") else "N/A"}'
|
|
120
122
|
)
|
|
121
123
|
response = await self.__router_client.send_message(
|
|
122
|
-
message, self.__user_state
|
|
124
|
+
message, self.__user_state, self.__platform_state
|
|
123
125
|
)
|
|
124
126
|
|
|
125
127
|
if response:
|
|
126
|
-
self.logger.
|
|
128
|
+
self.logger.info(
|
|
127
129
|
f'Mensagem enviada com sucesso | user={self.user_id}'
|
|
128
130
|
)
|
|
129
131
|
|
|
130
132
|
await asyncio.sleep(0.1)
|
|
131
133
|
except Exception as e:
|
|
132
|
-
raise Exception(
|
|
134
|
+
raise Exception(
|
|
135
|
+
f'[ChatID: {self.__user_state.chat_id}] - Erro ao enviar mensagem: {e}'
|
|
136
|
+
)
|
|
133
137
|
|
|
134
138
|
async def send(
|
|
135
139
|
self,
|
|
@@ -321,7 +325,9 @@ class UserCall: # noqa: PLR0904
|
|
|
321
325
|
async def load_identity(self, cpf: Optional[str] = None) -> UserIdentity:
|
|
322
326
|
try:
|
|
323
327
|
self.logger.debug(f'Consultando identidade | user={self.user_id}')
|
|
324
|
-
identity = await self.__router_client.get_identity(
|
|
328
|
+
identity = await self.__router_client.get_identity(
|
|
329
|
+
self.user_id, cpf=cpf
|
|
330
|
+
)
|
|
325
331
|
if self.__user_state.user is None:
|
|
326
332
|
self.__user_state.user = User()
|
|
327
333
|
self.__user_state.user.identity = identity
|
|
@@ -336,9 +342,13 @@ class UserCall: # noqa: PLR0904
|
|
|
336
342
|
async def load_userstate(self) -> UserState:
|
|
337
343
|
try:
|
|
338
344
|
self.logger.debug(f'Carregando userstate | user={self.user_id}')
|
|
339
|
-
resultado = await self.__router_client.get_session_by_chat_id(
|
|
345
|
+
resultado = await self.__router_client.get_session_by_chat_id(
|
|
346
|
+
self.__user_state.chat_id
|
|
347
|
+
)
|
|
340
348
|
if resultado is None:
|
|
341
|
-
raise ValueError(
|
|
349
|
+
raise ValueError(
|
|
350
|
+
'Sessão não encontrada para o chat_id informado.'
|
|
351
|
+
)
|
|
342
352
|
self.__user_state = resultado
|
|
343
353
|
self.logger.info(
|
|
344
354
|
f'Userstate carregado | user={self.user_id} | route={self.__user_state.route}'
|
|
@@ -400,6 +410,10 @@ class UserCall: # noqa: PLR0904
|
|
|
400
410
|
def observation(self):
|
|
401
411
|
return self.__user_state.observation_dict
|
|
402
412
|
|
|
413
|
+
@property
|
|
414
|
+
def platform_state(self) -> PlatformState:
|
|
415
|
+
return self.__platform_state
|
|
416
|
+
|
|
403
417
|
@property
|
|
404
418
|
def content_message(self):
|
|
405
419
|
return self.__content_message
|