pykabot 0.4.0__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.
- pykabot-0.4.0/LICENSE +21 -0
- pykabot-0.4.0/PKG-INFO +148 -0
- pykabot-0.4.0/PYPI_README.md +116 -0
- pykabot-0.4.0/README.md +116 -0
- pykabot-0.4.0/docs/DEPLOYMENT.md +49 -0
- pykabot-0.4.0/docs/LOCO.md +110 -0
- pykabot-0.4.0/docs/LOGIN.md +113 -0
- pykabot-0.4.0/docs/OPEN_PROFILE.md +98 -0
- pykabot-0.4.0/docs/PUBLISHING.md +62 -0
- pykabot-0.4.0/docs/REST.md +79 -0
- pykabot-0.4.0/docs/THIRD_PARTY_NOTICES.md +130 -0
- pykabot-0.4.0/examples/channel_bot.py +34 -0
- pykabot-0.4.0/examples/open_profile_loop.py +65 -0
- pykabot-0.4.0/examples/personal_bot.py +52 -0
- pykabot-0.4.0/examples/text_bot.py +25 -0
- pykabot-0.4.0/pyproject.toml +60 -0
- pykabot-0.4.0/src/kabot/__init__.py +37 -0
- pykabot-0.4.0/src/kabot/__main__.py +3 -0
- pykabot-0.4.0/src/kabot/bot.py +132 -0
- pykabot-0.4.0/src/kabot/cli.py +310 -0
- pykabot-0.4.0/src/kabot/loco/__init__.py +57 -0
- pykabot-0.4.0/src/kabot/loco/adapter.py +62 -0
- pykabot-0.4.0/src/kabot/loco/auth.py +367 -0
- pykabot-0.4.0/src/kabot/loco/chats.py +135 -0
- pykabot-0.4.0/src/kabot/loco/client.py +437 -0
- pykabot-0.4.0/src/kabot/loco/crypto.py +132 -0
- pykabot-0.4.0/src/kabot/loco/gui.py +258 -0
- pykabot-0.4.0/src/kabot/loco/interactive.py +255 -0
- pykabot-0.4.0/src/kabot/loco/live_test.py +270 -0
- pykabot-0.4.0/src/kabot/loco/open_profile.py +111 -0
- pykabot-0.4.0/src/kabot/loco/packet.py +197 -0
- pykabot-0.4.0/src/kabot/loco/session.py +156 -0
- pykabot-0.4.0/src/kabot/loco/storage.py +229 -0
- pykabot-0.4.0/src/kabot/loco/transport.py +139 -0
- pykabot-0.4.0/src/kabot/models.py +125 -0
- pykabot-0.4.0/src/kabot/py.typed +0 -0
- pykabot-0.4.0/src/kabot/rest.py +412 -0
- pykabot-0.4.0/src/kabot/server.py +127 -0
- pykabot-0.4.0/src/kabot/state.py +75 -0
- pykabot-0.4.0/tests/test_bot.py +99 -0
- pykabot-0.4.0/tests/test_cli.py +118 -0
- pykabot-0.4.0/tests/test_loco_auth.py +267 -0
- pykabot-0.4.0/tests/test_loco_chats.py +103 -0
- pykabot-0.4.0/tests/test_loco_crypto.py +106 -0
- pykabot-0.4.0/tests/test_loco_integration.py +239 -0
- pykabot-0.4.0/tests/test_loco_interactive.py +226 -0
- pykabot-0.4.0/tests/test_loco_live_test.py +416 -0
- pykabot-0.4.0/tests/test_loco_open_profile.py +201 -0
- pykabot-0.4.0/tests/test_loco_packet.py +122 -0
- pykabot-0.4.0/tests/test_loco_profiles.py +51 -0
- pykabot-0.4.0/tests/test_loco_session.py +100 -0
- pykabot-0.4.0/tests/test_loco_storage.py +179 -0
- pykabot-0.4.0/tests/test_loco_tls.py +215 -0
- pykabot-0.4.0/tests/test_rest.py +246 -0
- pykabot-0.4.0/tests/test_server.py +120 -0
- pykabot-0.4.0/tools/build_release.py +116 -0
pykabot-0.4.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Kabot contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
pykabot-0.4.0/PKG-INFO
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pykabot
|
|
3
|
+
Version: 0.4.0
|
|
4
|
+
Summary: Kakao channel bots, standalone Android-profile sessions and official message APIs
|
|
5
|
+
Author: Kabot contributors
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
License-File: docs/THIRD_PARTY_NOTICES.md
|
|
9
|
+
Keywords: asyncio,chatbot,kakao,kakaotalk,loco
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: Operating System :: OS Independent
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Topic :: Communications :: Chat
|
|
17
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
18
|
+
Requires-Python: >=3.11
|
|
19
|
+
Requires-Dist: fastapi<1,>=0.115
|
|
20
|
+
Requires-Dist: httpx<1,>=0.27
|
|
21
|
+
Requires-Dist: pydantic<3,>=2.8
|
|
22
|
+
Requires-Dist: uvicorn<1,>=0.30
|
|
23
|
+
Provides-Extra: dev
|
|
24
|
+
Requires-Dist: build<2,>=1.2; extra == 'dev'
|
|
25
|
+
Requires-Dist: pytest<10,>=8; extra == 'dev'
|
|
26
|
+
Requires-Dist: ruff<1,>=0.9; extra == 'dev'
|
|
27
|
+
Requires-Dist: twine<7,>=6.1; extra == 'dev'
|
|
28
|
+
Provides-Extra: loco
|
|
29
|
+
Requires-Dist: cryptography<50,>=44; extra == 'loco'
|
|
30
|
+
Requires-Dist: pymongo<5,>=4.10; extra == 'loco'
|
|
31
|
+
Description-Content-Type: text/markdown
|
|
32
|
+
|
|
33
|
+
# Kabot Python
|
|
34
|
+
|
|
35
|
+
**카카오톡 앱 설치 없이 운영하는 Python 카카오톡 봇 라이브러리.**
|
|
36
|
+
|
|
37
|
+
Python 3.11 이상에서 채널 챗봇 서버, 공식 메시지 REST API,
|
|
38
|
+
실험용 개인 계정·일반채팅·오픈채팅 LOCO 클라이언트를 제공합니다.
|
|
39
|
+
카카오의 공식 SDK가 아닙니다.
|
|
40
|
+
|
|
41
|
+
## 설치
|
|
42
|
+
|
|
43
|
+
```console
|
|
44
|
+
python -m pip install kabot-python
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
개인 계정·오픈채팅 기능을 사용하려면:
|
|
48
|
+
|
|
49
|
+
```console
|
|
50
|
+
python -m pip install "kabot-python[loco]"
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
배포 이름은 `kabot-python`, Python import 이름과 실행 명령은 `kabot`입니다.
|
|
54
|
+
Windows, Linux, macOS에서 사용할 수 있는 순수 Python 패키지입니다.
|
|
55
|
+
|
|
56
|
+
## 네트워크 없이 봇 만들기
|
|
57
|
+
|
|
58
|
+
```console
|
|
59
|
+
kabot init mybot.py
|
|
60
|
+
kabot chat mybot:bot
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
`/도움말`, `/안녕 철수`, `/방문`, `/종료`를 입력해 볼 수 있습니다.
|
|
64
|
+
이 시뮬레이터는 실제 카카오톡 메시지를 전송하지 않습니다.
|
|
65
|
+
|
|
66
|
+
```python
|
|
67
|
+
from kabot import Bot, SQLiteStore
|
|
68
|
+
|
|
69
|
+
bot = Bot(store=SQLiteStore("mybot.sqlite3"))
|
|
70
|
+
|
|
71
|
+
@bot.command("안녕")
|
|
72
|
+
def hello(ctx):
|
|
73
|
+
return f"안녕하세요, {ctx.args or '친구'}님!"
|
|
74
|
+
|
|
75
|
+
@bot.command("방문")
|
|
76
|
+
def visit(ctx):
|
|
77
|
+
count = ctx.store.increment(ctx.scope, "visits")
|
|
78
|
+
return f"{count}번째 방문입니다."
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
동기·비동기 핸들러, 정규식 매칭, 액션, 전처리와 SQLite 사용자 상태를 지원합니다.
|
|
82
|
+
|
|
83
|
+
## 채널 챗봇
|
|
84
|
+
|
|
85
|
+
```console
|
|
86
|
+
kabot secret
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
생성된 값을 `KABOT_WEBHOOK_SECRET` 환경변수에 설정한 뒤 실행합니다.
|
|
90
|
+
|
|
91
|
+
```console
|
|
92
|
+
kabot run mybot:bot
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
공개 HTTPS 서버와 카카오 챗봇 관리자센터의 스킬 연결이 필요합니다.
|
|
96
|
+
스킬 주소는 `https://YOUR_HOST/skill/YOUR_WEBHOOK_SECRET`입니다.
|
|
97
|
+
텍스트·카드·이미지·버튼 응답과, 별도 콜백 설정이 필요한 지연 응답을 지원합니다.
|
|
98
|
+
공식 메시지 REST API는 별도의 카카오 개발자 앱, OAuth 동의 및 권한이 필요합니다.
|
|
99
|
+
|
|
100
|
+
## 개인 계정·오픈채팅
|
|
101
|
+
|
|
102
|
+
```console
|
|
103
|
+
kabot login
|
|
104
|
+
kabot chats
|
|
105
|
+
kabot init personal_bot.py --personal
|
|
106
|
+
kabot personal personal_bot:bot --chat-id YOUR_CHAT_ID
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
`YOUR_CHAT_ID`를 `kabot chats`에 표시된 실제 숫자 ID로 바꾸세요.
|
|
110
|
+
계정 비밀번호와 세션 파일 암호는 실행한 터미널에서 직접 입력합니다.
|
|
111
|
+
최초 로그인은 기기 등록을 승인할 휴대폰이 필요할 수 있습니다.
|
|
112
|
+
서버에는 카카오톡 앱이 필요 없습니다. GUI 입력 창은 Tkinter가 설치된 데스크톱에서
|
|
113
|
+
`kabot gui --mode login`으로 열 수 있습니다.
|
|
114
|
+
|
|
115
|
+
Android 26.8.2 프로필의 로그인·기기 등록, 암호화 세션 저장, 방 목록 조회,
|
|
116
|
+
실시간 텍스트 수신·전송을 구현했습니다. 실제 오픈채팅에서 명령 수신과
|
|
117
|
+
1회 답장 도착을 확인했습니다. 모든 환경·계정에서의 호환성을 보장하지 않습니다.
|
|
118
|
+
자동 토큰 갱신·자동 재접속·미디어 업로드·비밀채팅은 아직 지원하지 않습니다.
|
|
119
|
+
|
|
120
|
+
## 오픈채팅 프로필 순환 변경
|
|
121
|
+
|
|
122
|
+
로그인된 `PersonalClient`에서 기본·익명·기존 오픈프로필로 전환할 수 있습니다.
|
|
123
|
+
다음은 이미 연결된 `client`를 사용하는 예시입니다.
|
|
124
|
+
|
|
125
|
+
```python
|
|
126
|
+
from kabot.loco import OpenChatProfile
|
|
127
|
+
|
|
128
|
+
await client.loopchange(
|
|
129
|
+
chat_id,
|
|
130
|
+
[OpenChatProfile.link(profile_a_id), OpenChatProfile.link(profile_b_id)],
|
|
131
|
+
interval=60,
|
|
132
|
+
max_changes=10,
|
|
133
|
+
)
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
`max_changes`를 생략하면 계속 반복하며 `stop_event=asyncio.Event()`로 중지할 수 있습니다.
|
|
137
|
+
서버 오류 시 중단하고, 중지 후 마지막 프로필을 유지합니다.
|
|
138
|
+
단독 실행 시에도 LOCO 푸시 이벤트를 소비해야 하며, 봇의 메시지 소비 루프와 함께
|
|
139
|
+
실행할 수 있습니다. 프로필 변경은 모의 테스트만 완료했으며 실계정 반영은 미검증입니다.
|
|
140
|
+
|
|
141
|
+
```console
|
|
142
|
+
kabot open-profile --help
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## 라이선스
|
|
146
|
+
|
|
147
|
+
MIT. 공개 프로토콜 참고 소스의 라이선스·저작권 고지는 배포 파일의
|
|
148
|
+
`kabot/THIRD_PARTY_NOTICES.md` 및 라이선스 메타데이터에 포함되어 있습니다.
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# Kabot Python
|
|
2
|
+
|
|
3
|
+
**카카오톡 앱 설치 없이 운영하는 Python 카카오톡 봇 라이브러리.**
|
|
4
|
+
|
|
5
|
+
Python 3.11 이상에서 채널 챗봇 서버, 공식 메시지 REST API,
|
|
6
|
+
실험용 개인 계정·일반채팅·오픈채팅 LOCO 클라이언트를 제공합니다.
|
|
7
|
+
카카오의 공식 SDK가 아닙니다.
|
|
8
|
+
|
|
9
|
+
## 설치
|
|
10
|
+
|
|
11
|
+
```console
|
|
12
|
+
python -m pip install kabot-python
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
개인 계정·오픈채팅 기능을 사용하려면:
|
|
16
|
+
|
|
17
|
+
```console
|
|
18
|
+
python -m pip install "kabot-python[loco]"
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
배포 이름은 `kabot-python`, Python import 이름과 실행 명령은 `kabot`입니다.
|
|
22
|
+
Windows, Linux, macOS에서 사용할 수 있는 순수 Python 패키지입니다.
|
|
23
|
+
|
|
24
|
+
## 네트워크 없이 봇 만들기
|
|
25
|
+
|
|
26
|
+
```console
|
|
27
|
+
kabot init mybot.py
|
|
28
|
+
kabot chat mybot:bot
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
`/도움말`, `/안녕 철수`, `/방문`, `/종료`를 입력해 볼 수 있습니다.
|
|
32
|
+
이 시뮬레이터는 실제 카카오톡 메시지를 전송하지 않습니다.
|
|
33
|
+
|
|
34
|
+
```python
|
|
35
|
+
from kabot import Bot, SQLiteStore
|
|
36
|
+
|
|
37
|
+
bot = Bot(store=SQLiteStore("mybot.sqlite3"))
|
|
38
|
+
|
|
39
|
+
@bot.command("안녕")
|
|
40
|
+
def hello(ctx):
|
|
41
|
+
return f"안녕하세요, {ctx.args or '친구'}님!"
|
|
42
|
+
|
|
43
|
+
@bot.command("방문")
|
|
44
|
+
def visit(ctx):
|
|
45
|
+
count = ctx.store.increment(ctx.scope, "visits")
|
|
46
|
+
return f"{count}번째 방문입니다."
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
동기·비동기 핸들러, 정규식 매칭, 액션, 전처리와 SQLite 사용자 상태를 지원합니다.
|
|
50
|
+
|
|
51
|
+
## 채널 챗봇
|
|
52
|
+
|
|
53
|
+
```console
|
|
54
|
+
kabot secret
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
생성된 값을 `KABOT_WEBHOOK_SECRET` 환경변수에 설정한 뒤 실행합니다.
|
|
58
|
+
|
|
59
|
+
```console
|
|
60
|
+
kabot run mybot:bot
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
공개 HTTPS 서버와 카카오 챗봇 관리자센터의 스킬 연결이 필요합니다.
|
|
64
|
+
스킬 주소는 `https://YOUR_HOST/skill/YOUR_WEBHOOK_SECRET`입니다.
|
|
65
|
+
텍스트·카드·이미지·버튼 응답과, 별도 콜백 설정이 필요한 지연 응답을 지원합니다.
|
|
66
|
+
공식 메시지 REST API는 별도의 카카오 개발자 앱, OAuth 동의 및 권한이 필요합니다.
|
|
67
|
+
|
|
68
|
+
## 개인 계정·오픈채팅
|
|
69
|
+
|
|
70
|
+
```console
|
|
71
|
+
kabot login
|
|
72
|
+
kabot chats
|
|
73
|
+
kabot init personal_bot.py --personal
|
|
74
|
+
kabot personal personal_bot:bot --chat-id YOUR_CHAT_ID
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
`YOUR_CHAT_ID`를 `kabot chats`에 표시된 실제 숫자 ID로 바꾸세요.
|
|
78
|
+
계정 비밀번호와 세션 파일 암호는 실행한 터미널에서 직접 입력합니다.
|
|
79
|
+
최초 로그인은 기기 등록을 승인할 휴대폰이 필요할 수 있습니다.
|
|
80
|
+
서버에는 카카오톡 앱이 필요 없습니다. GUI 입력 창은 Tkinter가 설치된 데스크톱에서
|
|
81
|
+
`kabot gui --mode login`으로 열 수 있습니다.
|
|
82
|
+
|
|
83
|
+
Android 26.8.2 프로필의 로그인·기기 등록, 암호화 세션 저장, 방 목록 조회,
|
|
84
|
+
실시간 텍스트 수신·전송을 구현했습니다. 실제 오픈채팅에서 명령 수신과
|
|
85
|
+
1회 답장 도착을 확인했습니다. 모든 환경·계정에서의 호환성을 보장하지 않습니다.
|
|
86
|
+
자동 토큰 갱신·자동 재접속·미디어 업로드·비밀채팅은 아직 지원하지 않습니다.
|
|
87
|
+
|
|
88
|
+
## 오픈채팅 프로필 순환 변경
|
|
89
|
+
|
|
90
|
+
로그인된 `PersonalClient`에서 기본·익명·기존 오픈프로필로 전환할 수 있습니다.
|
|
91
|
+
다음은 이미 연결된 `client`를 사용하는 예시입니다.
|
|
92
|
+
|
|
93
|
+
```python
|
|
94
|
+
from kabot.loco import OpenChatProfile
|
|
95
|
+
|
|
96
|
+
await client.loopchange(
|
|
97
|
+
chat_id,
|
|
98
|
+
[OpenChatProfile.link(profile_a_id), OpenChatProfile.link(profile_b_id)],
|
|
99
|
+
interval=60,
|
|
100
|
+
max_changes=10,
|
|
101
|
+
)
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
`max_changes`를 생략하면 계속 반복하며 `stop_event=asyncio.Event()`로 중지할 수 있습니다.
|
|
105
|
+
서버 오류 시 중단하고, 중지 후 마지막 프로필을 유지합니다.
|
|
106
|
+
단독 실행 시에도 LOCO 푸시 이벤트를 소비해야 하며, 봇의 메시지 소비 루프와 함께
|
|
107
|
+
실행할 수 있습니다. 프로필 변경은 모의 테스트만 완료했으며 실계정 반영은 미검증입니다.
|
|
108
|
+
|
|
109
|
+
```console
|
|
110
|
+
kabot open-profile --help
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## 라이선스
|
|
114
|
+
|
|
115
|
+
MIT. 공개 프로토콜 참고 소스의 라이선스·저작권 고지는 배포 파일의
|
|
116
|
+
`kabot/THIRD_PARTY_NOTICES.md` 및 라이선스 메타데이터에 포함되어 있습니다.
|
pykabot-0.4.0/README.md
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# Kabot Python
|
|
2
|
+
|
|
3
|
+
**서버에 카카오톡을 설치하지 않고 실행하는 카카오톡 봇 파이썬 라이브러리.** Python 3.11+, Windows/Linux/macOS에서 사용합니다. 채널 챗봇, 공식 메시지 API, 실험용 개인 계정·단체방 클라이언트를 제공합니다.
|
|
4
|
+
|
|
5
|
+
| 기능 | 현재 상태 |
|
|
6
|
+
|---|---|
|
|
7
|
+
| 채널에서 사용자 질문에 응답 | 구현, 공개 HTTPS 스킬 서버 연결 필요 |
|
|
8
|
+
| 명령어/정규식/액션/전처리 | 구현, 동기·비동기 핸들러 |
|
|
9
|
+
| 카드/이미지/바로가기/긴 텍스트 | 구현 |
|
|
10
|
+
| 사용자별 메모·방문 횟수·TTL | SQLite로 구현 |
|
|
11
|
+
| 시간이 오래 걸리는 작업의 콜백 | 구현, 카카오 블록 활성화 + 정확한 호스트 허용 설정 필요 |
|
|
12
|
+
| 개인 계정의 나에게 보내기 | 공식 OAuth/API로 구현 |
|
|
13
|
+
| 친구에게 보내기 | 공식 API로 구현, 권한·동의·수신 대상 제한 적용 |
|
|
14
|
+
| 개인 계정·단체방 LOCO 수신/텍스트 응답 | 실제 오픈채팅에서 명령 수신·1회 답장 및 사용자 수신 확인 |
|
|
15
|
+
| 비밀번호 로그인·휴대폰 기기 등록·토큰 발급 | Android26.8.2 프로필 구현, 실제 사용자 계정 인증·세션 저장 확인 |
|
|
16
|
+
| 암호화 세션·로컬 입력 창 | 0.3.0 구현, 세션 암호로 재사용 |
|
|
17
|
+
| 참여 중인 오픈채팅 텍스트 | 명시적 `--allow-open` 테스트·실제 송수신 확인, 서버 방 이름 조회 |
|
|
18
|
+
| 자동 토큰 갱신·오픈채팅 참여/관리·E2E 비밀채팅 | 미구현 |
|
|
19
|
+
|
|
20
|
+
운영 서버에는 카카오톡 앱이 필요 없습니다. 채널 방식은 채널/챗봇 설정이 필요하고, 공식 메시지 API는 개발자 앱과 사용자 동의가 필요합니다. 실험용 개인 계정 방식은 기존 계정과 새 기기 등록을 승인할 휴대폰을 사용합니다. [개인 계정 로그인·실행 안내](docs/LOGIN.md)를 참조하세요.
|
|
21
|
+
|
|
22
|
+
## 설치 및 바로 실행
|
|
23
|
+
|
|
24
|
+
PowerShell에서 이 프로젝트 폴더를 열고:
|
|
25
|
+
|
|
26
|
+
```powershell
|
|
27
|
+
python -m venv .venv
|
|
28
|
+
.\.venv\Scripts\python.exe -m pip install -e .
|
|
29
|
+
.\.venv\Scripts\kabot.exe init mybot.py
|
|
30
|
+
.\.venv\Scripts\kabot.exe chat mybot:bot
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
로컬에서 `/도움말`, `/안녕 철수`, `/방문`, `/메모 내일 회의`, `/메모확인`을 입력해 보세요. 실제 메시지는 전송하지 않습니다. `init`은 기존 파일을 덮어쓰지 않습니다. Linux/macOS에서는 `.venv/bin/python`, `.venv/bin/kabot`을 사용합니다.
|
|
34
|
+
|
|
35
|
+
```python
|
|
36
|
+
from kabot import Bot, SQLiteStore, create_app
|
|
37
|
+
|
|
38
|
+
bot = Bot(store=SQLiteStore("mybot.sqlite3"))
|
|
39
|
+
|
|
40
|
+
@bot.command("안녕")
|
|
41
|
+
def hello(ctx):
|
|
42
|
+
return f"안녕하세요, {ctx.args or '친구'}님!"
|
|
43
|
+
|
|
44
|
+
@bot.command("방문")
|
|
45
|
+
def visit(ctx):
|
|
46
|
+
count = ctx.store.increment(ctx.scope, "visits")
|
|
47
|
+
return f"{count}번째 방문입니다."
|
|
48
|
+
|
|
49
|
+
@bot.hears(r"^문의 (.+)$")
|
|
50
|
+
async def question(ctx):
|
|
51
|
+
return f"문의: {ctx.match[1]}"
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
첫 번째로 일치하는 핸들러 하나가 실행됩니다. 포괄적인 `@bot.on_message()`는 마지막에 등록하세요. `@bot.action("액션명")`으로 스킬 액션 이름에 연결할 수 있습니다. `@bot.before` 전처리에서 응답을 반환하면 실행을 중단하고, `None`이면 계속합니다. `ctx.params`는 action.params, `ctx.user_id`는 봇 범위 사용자 ID이며 카카오 계정 ID/친구 UUID와 다릅니다.
|
|
55
|
+
|
|
56
|
+
## 오픈채팅 프로필 변경
|
|
57
|
+
|
|
58
|
+
0.4.0에서 `get_open_profile()`, `list_open_links()`, `change_open_profile()`과
|
|
59
|
+
프로필을 순서대로 반복 적용하는 `loopchange()`를 추가했습니다. 기본 프로필·익명
|
|
60
|
+
프로필·기존 오픈프로필로 전환하며, 간격·최대 횟수·중지 신호를 지정할 수 있습니다.
|
|
61
|
+
구현 및 모의 테스트를 완료했으며 실제 계정의 프로필 변경은 아직 검증하지 않았습니다.
|
|
62
|
+
[사용법과 실행 예제](docs/OPEN_PROFILE.md)를 참고하세요.
|
|
63
|
+
|
|
64
|
+
## 실제 채널에 연결
|
|
65
|
+
|
|
66
|
+
```powershell
|
|
67
|
+
$env:KABOT_WEBHOOK_SECRET = .\.venv\Scripts\kabot.exe secret
|
|
68
|
+
$env:KABOT_BOT_ID = '챗봇 관리자센터의 봇 ID'
|
|
69
|
+
.\.venv\Scripts\kabot.exe run mybot:bot
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
서버 앞에 HTTPS 리버스 프록시를 구성하고, 챗봇 관리자센터의 스킬 URL을 `https://내도메인/skill/생성한비밀값`으로 지정합니다. 실제 비밀값은 위 환경변수에 저장된 값입니다. 블록 또는 폴백 블록에 이 스킬을 연결하고 응답에서 **스킬데이터 사용**을 선택한 뒤 채널에 연결·배포하세요. 서버 기본 포트는 8000이며 로컬 인터페이스에 바인딩합니다. 컨테이너는 `--host 0.0.0.0`을 사용합니다. 상세 내용은 [배포 안내](docs/DEPLOYMENT.md)를 참조하세요.
|
|
73
|
+
|
|
74
|
+
개인 계정의 나에게/친구에게 메시지 보내기, OAuth 로그인과 갱신은 [공식 REST API 안내](docs/REST.md)에 있습니다.
|
|
75
|
+
|
|
76
|
+
0.3.0의 개인 계정·단체방 프로토콜 계층은 [LOCO 안내](docs/LOCO.md),
|
|
77
|
+
계정 입력과 암호화 세션 재사용은 [로그인 안내](docs/LOGIN.md)에 있습니다.
|
|
78
|
+
`pip install -e '.[loco]'`로 추가 의존성을 설치합니다.
|
|
79
|
+
|
|
80
|
+
## 카드, 이미지, 버튼
|
|
81
|
+
|
|
82
|
+
```python
|
|
83
|
+
from kabot import card, link_button, quick_reply, text, image
|
|
84
|
+
|
|
85
|
+
answer = card("주문 안내", "주문 현황을 확인하세요.", "https://example.com/product.png",
|
|
86
|
+
buttons=[link_button("주문 보기", "https://example.com/orders")])
|
|
87
|
+
answer = answer.with_quick_replies(quick_reply("도움말", "/도움말"))
|
|
88
|
+
long_answer = text("긴 텍스트") # 최대 3000자를 1000자씩 최대 3개 말풍선으로 분할
|
|
89
|
+
picture = image("https://example.com/photo.jpg", "상품 사진")
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
`Response(outputs=[...])`로 추가 공식 응답 형식을 직접 구성할 수도 있습니다. 이 경우 내부 필드 규격은 호출자가 확인합니다. 기본 빌더는 길이와 개수 제한을 검사하며 임의로 내용을 잘라내지 않습니다. API의 상세 제약은 [카카오 스킬 응답 규격](https://kakaobusiness.gitbook.io/main/tool/chatbot/skill_guide/answer_json_format)을 따릅니다.
|
|
93
|
+
|
|
94
|
+
## 느린 작업과 상태 저장
|
|
95
|
+
|
|
96
|
+
`@bot.command("분석", deferred=True)`는 콜백을 통해 응답합니다. 카카오 블록의 콜백을 활성화하고 실제 카카오가 제공하는 콜백 URL의 정확한 호스트를 운영자가 검증한 뒤 `KABOT_CALLBACK_HOSTS`에 설정해야 합니다. 설정하지 않으면 외부 콜백은 전송되지 않습니다. [운영 제한과 콜백 설정](docs/DEPLOYMENT.md)을 먼저 확인하세요.
|
|
97
|
+
|
|
98
|
+
`SQLiteStore`는 사용자 상태를 JSON으로 보관하고 TTL을 지원합니다. 사용자 범위는 `ctx.scope`를 쓰세요. `increment`는 여러 동시 요청에도 원자적으로 증가합니다. `get` 후 `set`을 하는 임의의 갱신은 원자적이지 않습니다. 파일 백업·접근 권한·보관 기간은 운영자가 관리합니다.
|
|
99
|
+
|
|
100
|
+
## 검증과 역분석
|
|
101
|
+
|
|
102
|
+
PyPI 배포용 빌드·검증은 `python tools/build_release.py`로 실행합니다.
|
|
103
|
+
현재 버전의 배포 파일만 `dist/pypi/0.4.0/`에 만들며 업로드는 하지 않습니다.
|
|
104
|
+
[PyPI 배포 안내](docs/PUBLISHING.md)를 참고하세요.
|
|
105
|
+
|
|
106
|
+
```powershell
|
|
107
|
+
.\.venv\Scripts\python.exe -m pip install -e '.[dev,loco]'
|
|
108
|
+
.\.venv\Scripts\python.exe -m pytest -q
|
|
109
|
+
.\.venv\Scripts\python.exe -m build
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
자동 테스트는 HTTP 모의 서버로 실행하며 실계정 로그인을 하거나 카카오톡 메시지를 발송하지 않습니다. 실계정 인증·채널 배포·실제 도착 여부는 별도 확인이 필요합니다.
|
|
113
|
+
|
|
114
|
+
REA PE 분석 근거는 `docs/rea-evidence.json`, 실제 IDA Pro 9.3 정적 분석 결과는 [IDA 분석 보고서](docs/IDA_ANALYSIS.md)에 있습니다. 첫 압축 계층 약 20.9MB를 오프라인 복원하고 IDA로 다시 분석했으나 로그인/단체방 프로토콜까지 복구하지는 못했습니다. 실험용 LOCO 계층은 고정한 MIT 공개 소스를 별도 근거로 사용했습니다. 분석에 사용한 원본 실행 파일·IDA 데이터베이스는 배포 패키지에 포함하지 않습니다.
|
|
115
|
+
|
|
116
|
+
이 프로젝트는 카카오의 공식 SDK가 아닙니다. 라이선스: MIT.
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# 채널 봇 배포 및 운영
|
|
2
|
+
|
|
3
|
+
## 연결 순서
|
|
4
|
+
|
|
5
|
+
1. 카카오 채널과 챗봇을 준비하고 챗봇 관리자센터에서 스킬을 만듭니다.
|
|
6
|
+
2. Kabot 서버를 공개 HTTPS 도메인 뒤에서 실행합니다. `/healthz`로 프로세스 상태를 확인합니다.
|
|
7
|
+
3. 충분히 긴 무작위 비밀값을 생성해서 `KABOT_WEBHOOK_SECRET`에 보관합니다. 재시작 후에도 동일 값을 주입해야 합니다.
|
|
8
|
+
4. 스킬 URL을 `https://your-domain/skill/<secret>`으로 지정합니다. `KABOT_BOT_ID`도 지정해서 다른 봇의 요청을 거부합니다.
|
|
9
|
+
5. 블록에 스킬을 연결하고 스킬데이터를 응답으로 사용하도록 설정합니다. 여러 명령을 처리하려면 폴백 블록도 이 스킬로 연결하세요.
|
|
10
|
+
6. 챗봇을 채널에 연결하고 배포한 뒤 사용자의 카카오톡에서 실제 대화를 확인합니다.
|
|
11
|
+
|
|
12
|
+
비밀 경로는 라이브러리에서 제공하는 접근 제어입니다. 카카오가 서명한 요청임을 암호학적으로 확인하는 기능은 아닙니다. 경로가 유출되면 교체하세요. 리버스 프록시에서도 `/skill/*` 경로·요청 본문·쿼리를 로그에 남기지 않도록 설정하세요. CLI의 Uvicorn access log는 비활성화되어 있습니다. 요청률 제한과 TLS는 앞단 프록시에서 구성합니다.
|
|
13
|
+
|
|
14
|
+
## 시간 제한
|
|
15
|
+
|
|
16
|
+
카카오 스킬 요청은 짧은 시간 내 응답해야 합니다. Kabot 기본 핸들러 제한은 4초입니다. 비동기 작업은 취소될 수 있지만 동기 핸들러는 Python 스레드에서 실행되어 타임아웃 후에도 작업이 계속될 수 있습니다. 외부 결제·주문·발송 같은 작업은 애플리케이션의 중복 실행 방지 키/트랜잭션으로 보호하세요. Kabot은 같은 발화를 반복했다는 이유로 요청을 중복 취급하지 않습니다.
|
|
17
|
+
|
|
18
|
+
## 콜백
|
|
19
|
+
|
|
20
|
+
```python
|
|
21
|
+
import os
|
|
22
|
+
from kabot import Bot, create_app
|
|
23
|
+
|
|
24
|
+
bot = Bot()
|
|
25
|
+
|
|
26
|
+
@bot.command("분석", deferred=True)
|
|
27
|
+
async def analyze(ctx):
|
|
28
|
+
result = await your_async_analysis(ctx.args) # 애플리케이션에서 구현
|
|
29
|
+
return result
|
|
30
|
+
|
|
31
|
+
app = create_app(
|
|
32
|
+
bot,
|
|
33
|
+
webhook_secret=os.environ["KABOT_WEBHOOK_SECRET"],
|
|
34
|
+
expected_bot_id=os.environ["KABOT_BOT_ID"],
|
|
35
|
+
callback_hosts=("실제-검증한-카카오-콜백-호스트",),
|
|
36
|
+
)
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
위 호스트 문자열은 예시 자리표시자이므로 실제 검증한 ASCII DNS 호스트명으로 바꿔야 합니다. 임의의 도메인을 추측해서 허용하지 마세요. 정확한 HTTPS 호스트와 443 포트만 허용하며 URL 사용자정보/fragment 및 리다이렉트를 거부합니다. 운영 네트워크의 egress 제어도 적용하세요. CLI는 `KABOT_CALLBACK_HOSTS`의 쉼표 구분 호스트 목록을 사용합니다.
|
|
40
|
+
|
|
41
|
+
콜백 활성화된 블록에서 `userRequest.callbackUrl`을 받으면, 서버가 `{version:"2.0", useCallback:true}`를 먼저 반환하고 배경 작업으로 결과를 한 번 POST합니다. 문서는 도입부에서 5분 유효, 오류표에서는 1분 이내라는 서로 다른 안내를 포함합니다. 이 구현은 보수적으로 처리 작업을 기본 40초(설정 상한 45초)로 제한하며, POST 응답은 HTTP 성공과 `status=SUCCESS` 모두 확인합니다. 실패는 URL/토큰 없이 오류 종류를 기록합니다. 단일 사용 토큰이므로 POST는 자동 재시도하지 않습니다.
|
|
42
|
+
|
|
43
|
+
FastAPI BackgroundTasks는 프로세스 내부 작업입니다. 서버 종료/충돌 때 작업이 유실될 수 있으며 영속 작업 큐가 아닙니다. 장시간 AI 작업·무거운 CPU 작업·대규모 운영에는 별도의 작업 큐와 관측 시스템을 연결해야 합니다. 테스트용 callback token은 실제 전송에 사용할 수 없다는 카카오 제한이 있습니다.
|
|
44
|
+
|
|
45
|
+
출처: [카카오 콜백 개발 가이드](https://kakaobusiness.gitbook.io/main/tool/chatbot/skill_guide/ai_chatbot_callback_guide), [스킬 개발 가이드](https://kakaobusiness.gitbook.io/main/tool/chatbot/skill_guide). 확인일: 2026-10-31.
|
|
46
|
+
|
|
47
|
+
## 패키징
|
|
48
|
+
|
|
49
|
+
프로젝트에서 `python -m build`로 wheel과 sdist를 만듭니다. 다른 서버에서는 `pip install /path/to/kabot_python-0.3.0-py3-none-any.whl`로 설치합니다. 개인 계정 기능은 LOCO 추가 의존성이 필요합니다. PyPI 업로드는 하지 않습니다. `docs/analysis`의 실행 파일과 IDA 데이터베이스, 사용자 세션 파일은 배포 대상에 포함하지 않습니다.
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# 개인 계정·단체방 LOCO 계층 (0.3.0)
|
|
2
|
+
|
|
3
|
+
0.3.0에는 **Android26.8.2 계정 인증, 휴대폰 기기 등록, 암호화 세션 저장**을 추가했습니다.
|
|
4
|
+
2026-11-08 사용자 직접 입력으로 실제 계정 인증과 채팅 서버 `LOGINLIST`가 성공했고,
|
|
5
|
+
채팅방 항목28개를 받았습니다. 이후 선택한 오픈채팅에서 다른 계정의 새 명령을 수신하고
|
|
6
|
+
답장1회의 서버 성공 응답과 사용자 화면의 실제 수신까지 확인했습니다.
|
|
7
|
+
사용 절차는 [로그인 안내](LOGIN.md)에 있습니다.
|
|
8
|
+
|
|
9
|
+
Android 프로필은 loco-wrapper의 고정된26.8.2 소스, 기존 macOS 프로필은 openkakao-cli
|
|
10
|
+
소스를 근거로 합니다. 두 프로필의 인증 필드와 암호화 방식을 섞지 않습니다. macOS
|
|
11
|
+
프로필은 참고용으로 유지하며 현재 실계정 확인은 Android 프로필에서 수행했습니다.
|
|
12
|
+
|
|
13
|
+
## 근거와 구현 범위
|
|
14
|
+
|
|
15
|
+
| 항목 | 구현/검증 상태 |
|
|
16
|
+
|---|---|
|
|
17
|
+
| 22바이트 little-endian 헤더 + BSON | 직접 바이트 fixture와 정수 범위·분할 파싱 테스트 |
|
|
18
|
+
| 64비트 사용자·채팅·로그 ID | `bson.Int64` 보존 테스트; float 변환 없음 |
|
|
19
|
+
| RSA-OAEP-SHA1 / AES-128-GCM | 로컬 RSA 복호화, NIST GCM 벡터, 변조 거부 테스트 |
|
|
20
|
+
| Android TLS 및 서비스 이름 | 실제 서버 CA 검증 성공, IP 배정 시 `kakao.com` 검증, 잘못된 이름 거부 테스트 |
|
|
21
|
+
| TCP 분할·합쳐진 패킷·암호화 레코드 재조립 | 로컬 테스트 |
|
|
22
|
+
| Booking → CHECKIN → LOGINLIST | 모의 응답과 실제 loopback TCP로 흐름 검증 |
|
|
23
|
+
| 동시 요청과 push 분리 | 요청 ID/메서드 대응, push 보존, 큐 초과 시 연결 중단 |
|
|
24
|
+
| MSG / SYNCMSG | flat, chatLog, chatLogs 구조와 ID 충돌 검사 |
|
|
25
|
+
| CHATONROOM / WRITE | 로컬 TCP 모의 서버에서 요청·응답 검증 |
|
|
26
|
+
| 개인/단체방 명령어 봇 어댑터 | 지정한 방·새 텍스트·타인 메시지만 처리, 중복 이벤트 억제 |
|
|
27
|
+
| 실제 계정 인증·LOGINLIST | 2026-11-08 사용자 직접 입력으로 확인 |
|
|
28
|
+
| 비밀번호 로그인·기기 등록·토큰 발급 | 구현, 비밀번호는 저장하지 않음 |
|
|
29
|
+
| 암호화 세션 파일 | scrypt + AES-256-GCM, GUI/CLI에서 사용자 암호로 열기 |
|
|
30
|
+
| 전체 방 목록·정식 방 이름 | LCHATLIST 페이지 + 읽기 전용 CHATINFO/INFOLINK |
|
|
31
|
+
| 참여 중인 오픈채팅 텍스트 | 명시적 `--allow-open`, 실제1회 송수신·사용자 수신 확인 |
|
|
32
|
+
| 첨부파일·이미지 발송·오픈채팅 참여/관리·E2E 비밀채팅 | 미구현 |
|
|
33
|
+
|
|
34
|
+
기존 패킷/암호화/메시지 필드의 출처는 고정한 공개 소스 커밋
|
|
35
|
+
`6ca6ea2fd05a6660c4a80c0b61b43b416653d1d5`입니다. Windows 실행 파일에서 이 규격을
|
|
36
|
+
직접 복구한 결과가 아닙니다. 네이티브 역분석 결과는 [IDA 기록](IDA_ANALYSIS.md),
|
|
37
|
+
참고 코드의 MIT 라이선스는 [서드파티 고지](THIRD_PARTY_NOTICES.md)에 구분했습니다.
|
|
38
|
+
|
|
39
|
+
## 설치
|
|
40
|
+
|
|
41
|
+
```powershell
|
|
42
|
+
.\.venv\Scripts\python.exe -m pip install -e '.[loco]'
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
다른 서버에서는 wheel 파일을 설치하고 `pymongo>=4.10,<5`, `cryptography>=44,<50`을
|
|
46
|
+
설치합니다. 이 프로젝트는 PyPI에 게시되지 않았습니다. `bson`이라는 별도 패키지를
|
|
47
|
+
설치하지 마세요. `pymongo`에 포함된 BSON을 씁니다. 기본 채널/공식 REST 기능은
|
|
48
|
+
이 optional dependency 없이 사용할 수 있습니다.
|
|
49
|
+
|
|
50
|
+
## 사용 형태
|
|
51
|
+
|
|
52
|
+
```python
|
|
53
|
+
from kabot import Bot
|
|
54
|
+
from kabot.loco import Credentials, PersonalClient, run_personal_bot
|
|
55
|
+
|
|
56
|
+
bot = Bot()
|
|
57
|
+
|
|
58
|
+
@bot.command("안녕")
|
|
59
|
+
async def hello(ctx):
|
|
60
|
+
return f"안녕하세요, {ctx.args or '친구'}님!"
|
|
61
|
+
|
|
62
|
+
async def run(credentials: Credentials, chat_ids: set[int]):
|
|
63
|
+
async with PersonalClient(credentials) as client:
|
|
64
|
+
await client.connect() # 실제 실행하면 서버 연결과 LOGINLIST를 한 번 시도
|
|
65
|
+
await run_personal_bot(bot, client, chat_ids=chat_ids)
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
`Credentials(user_id, oauth_token, device_uuid, app_version, profile="android")`는 Android
|
|
69
|
+
계정 인증으로 얻은 LOCO 세션 정보를 받습니다. 기본 `profile="mac"`는 기존 호환용입니다.
|
|
70
|
+
**공식 개발자 REST API 토큰과 서로 바꿔 쓸 수
|
|
71
|
+
있다고 가정하면 안 됩니다.** 로컬 앱·캐시·운영체제 자격 증명 저장소를 뒤져 자동으로
|
|
72
|
+
정보를 읽는 기능은 없습니다. 토큰·기기 ID는 객체 repr에서 숨깁니다.
|
|
73
|
+
|
|
74
|
+
`examples/personal_bot.py`에는 환경변수로 입력받는 실행 예제가 있습니다. 필요한 항목은
|
|
75
|
+
`KABOT_LOCO_USER_ID`, `KABOT_LOCO_TOKEN`, `KABOT_LOCO_DEVICE_UUID`,
|
|
76
|
+
`KABOT_LOCO_APP_VERSION`, `KABOT_LOCO_CHAT_IDS`(쉼표 구분 방 ID)입니다.
|
|
77
|
+
현재 호환성을 확인한 자격 증명이 없는 상태에서는 이 예제가 동작한다고 보장하지 않습니다.
|
|
78
|
+
|
|
79
|
+
## 연결과 실패 처리
|
|
80
|
+
|
|
81
|
+
- GUI/CLI 계정 로그인은 Android26.8.2 프로필을 생성합니다. 직접 `Credentials`를 만드는
|
|
82
|
+
코드는 사용할 프로필을 지정하세요.
|
|
83
|
+
- Android는 Booking/Checkin/채팅 모두 TLS를 사용합니다. 배정된 채팅 IP와 인증서의
|
|
84
|
+
서비스 이름 `kakao.com`을 분리해 정상 CA/호스트 검증을 유지합니다. 기존 macOS
|
|
85
|
+
프로필의 Checkin/채팅에는 참고 RSA+GCM 계층을 사용합니다.
|
|
86
|
+
- 참고 RSA 공개키는 소스에서 가져온 값이며 현행 서버 키로 독립 검증한 것은 아닙니다.
|
|
87
|
+
`PersonalClient(..., public_key_der=검증한키)`로 교체할 수 있습니다.
|
|
88
|
+
- `LocoStatusError.method`, `.status`로 서버 거부를 확인합니다. 특히 인증 실패를 자동
|
|
89
|
+
재시도하지 않습니다. 서버가 지정한 이동/퇴장도 연결을 멈추고 호출자에게 알립니다.
|
|
90
|
+
- 요청 타임아웃·취소·수신 파싱/인증 실패 시 연결을 닫습니다. WRITE 이후 응답이 없으면
|
|
91
|
+
실제 도착 여부가 불명확하므로 자동 재전송하지 않습니다.
|
|
92
|
+
- 수신 큐는 기본 256개입니다. 소비자가 뒤처지면 조용히 메시지를 버리는 대신
|
|
93
|
+
`EventOverflowError`로 연결을 중단합니다.
|
|
94
|
+
- 30초마다 PING을 보냅니다. 자동 재접속이나 과거 메시지 동기화는 구현하지 않았습니다.
|
|
95
|
+
- 봇 어댑터는 텍스트 응답만 지원하고, 일반 대화/자기 메시지/다른 방/비텍스트는 무시합니다.
|
|
96
|
+
중복 억제는 기본 4096개이며 프로세스 재시작 뒤에는 보존되지 않습니다.
|
|
97
|
+
애플리케이션의 영속 중복 처리나 exactly-once 보장을 대신하지 않습니다.
|
|
98
|
+
- `ctx.metadata`에 `chat_id`, `log_id`, `transport="loco"`를 제공합니다.
|
|
99
|
+
`ctx.scope`는 계정·방·발화자 범위입니다. 응답 오류는 무시하지 않고 실행을 중단합니다.
|
|
100
|
+
|
|
101
|
+
## 검증 실행
|
|
102
|
+
|
|
103
|
+
```powershell
|
|
104
|
+
.\.venv\Scripts\python.exe -m pip install -e '.[dev,loco]'
|
|
105
|
+
.\.venv\Scripts\python.exe -m pytest tests/test_loco_packet.py tests/test_loco_crypto.py tests/test_loco_session.py tests/test_loco_integration.py -q
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
위 자동 테스트의 토큰·RSA 비밀키·TCP 서버는 가짜 값/로컬 서버를 사용합니다. 자동
|
|
109
|
+
테스트와 별도로 사용자 직접 입력의 실제 계정 인증·LOGINLIST를 확인했습니다.
|
|
110
|
+
계정 정보나 채팅 내용을 테스트 fixture와 배포 파일에 포함하지 않습니다.
|