imbot-sdk-python 0.1.0__tar.gz → 0.1.1__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.
- {imbot_sdk_python-0.1.0 → imbot_sdk_python-0.1.1}/CHANGELOG.md +8 -0
- {imbot_sdk_python-0.1.0 → imbot_sdk_python-0.1.1}/MANIFEST.in +1 -0
- imbot_sdk_python-0.1.1/PKG-INFO +335 -0
- imbot_sdk_python-0.1.1/README.md +301 -0
- imbot_sdk_python-0.1.0/README.md → imbot_sdk_python-0.1.1/README.zh-CN.md +3 -1
- imbot_sdk_python-0.1.1/docs/API.md +170 -0
- imbot_sdk_python-0.1.0/docs/API.md → imbot_sdk_python-0.1.1/docs/API.zh-CN.md +2 -0
- imbot_sdk_python-0.1.1/docs/PROTOCOL.md +95 -0
- imbot_sdk_python-0.1.0/docs/PROTOCOL.md → imbot_sdk_python-0.1.1/docs/PROTOCOL.zh-CN.md +2 -0
- {imbot_sdk_python-0.1.0 → imbot_sdk_python-0.1.1}/imbot_sdk/__init__.py +1 -1
- imbot_sdk_python-0.1.1/imbot_sdk_python.egg-info/PKG-INFO +335 -0
- {imbot_sdk_python-0.1.0 → imbot_sdk_python-0.1.1}/imbot_sdk_python.egg-info/SOURCES.txt +3 -0
- {imbot_sdk_python-0.1.0 → imbot_sdk_python-0.1.1}/pyproject.toml +1 -1
- imbot_sdk_python-0.1.0/PKG-INFO +0 -296
- imbot_sdk_python-0.1.0/imbot_sdk_python.egg-info/PKG-INFO +0 -296
- {imbot_sdk_python-0.1.0 → imbot_sdk_python-0.1.1}/LICENSE +0 -0
- {imbot_sdk_python-0.1.0 → imbot_sdk_python-0.1.1}/examples/.env.example +0 -0
- {imbot_sdk_python-0.1.0 → imbot_sdk_python-0.1.1}/examples/echo_bot.py +0 -0
- {imbot_sdk_python-0.1.0 → imbot_sdk_python-0.1.1}/examples/quickstart.py +0 -0
- {imbot_sdk_python-0.1.0 → imbot_sdk_python-0.1.1}/examples/run.sh +0 -0
- {imbot_sdk_python-0.1.0 → imbot_sdk_python-0.1.1}/imbot_sdk/client.py +0 -0
- {imbot_sdk_python-0.1.0 → imbot_sdk_python-0.1.1}/imbot_sdk/consts.py +0 -0
- {imbot_sdk_python-0.1.0 → imbot_sdk_python-0.1.1}/imbot_sdk/data_accessor.py +0 -0
- {imbot_sdk_python-0.1.0 → imbot_sdk_python-0.1.1}/imbot_sdk/listeners.py +0 -0
- {imbot_sdk_python-0.1.0 → imbot_sdk_python-0.1.1}/imbot_sdk/messages/__init__.py +0 -0
- {imbot_sdk_python-0.1.0 → imbot_sdk_python-0.1.1}/imbot_sdk/messages/base.py +0 -0
- {imbot_sdk_python-0.1.0 → imbot_sdk_python-0.1.1}/imbot_sdk/messages/contents.py +0 -0
- {imbot_sdk_python-0.1.0 → imbot_sdk_python-0.1.1}/imbot_sdk/models.py +0 -0
- {imbot_sdk_python-0.1.0 → imbot_sdk_python-0.1.1}/imbot_sdk/pb/__init__.py +0 -0
- {imbot_sdk_python-0.1.0 → imbot_sdk_python-0.1.1}/imbot_sdk/pb/appmessages_pb2.py +0 -0
- {imbot_sdk_python-0.1.0 → imbot_sdk_python-0.1.1}/imbot_sdk/pb/chatroom_pb2.py +0 -0
- {imbot_sdk_python-0.1.0 → imbot_sdk_python-0.1.1}/imbot_sdk/pb/connect_pb2.py +0 -0
- {imbot_sdk_python-0.1.0 → imbot_sdk_python-0.1.1}/imbot_sdk/pb/rtcroom_pb2.py +0 -0
- {imbot_sdk_python-0.1.0 → imbot_sdk_python-0.1.1}/imbot_sdk/py.typed +0 -0
- {imbot_sdk_python-0.1.0 → imbot_sdk_python-0.1.1}/imbot_sdk_python.egg-info/dependency_links.txt +0 -0
- {imbot_sdk_python-0.1.0 → imbot_sdk_python-0.1.1}/imbot_sdk_python.egg-info/requires.txt +0 -0
- {imbot_sdk_python-0.1.0 → imbot_sdk_python-0.1.1}/imbot_sdk_python.egg-info/top_level.txt +0 -0
- {imbot_sdk_python-0.1.0 → imbot_sdk_python-0.1.1}/proto/appmessages.proto +0 -0
- {imbot_sdk_python-0.1.0 → imbot_sdk_python-0.1.1}/proto/chatroom.proto +0 -0
- {imbot_sdk_python-0.1.0 → imbot_sdk_python-0.1.1}/proto/connect.proto +0 -0
- {imbot_sdk_python-0.1.0 → imbot_sdk_python-0.1.1}/proto/gen.sh +0 -0
- {imbot_sdk_python-0.1.0 → imbot_sdk_python-0.1.1}/proto/rtcroom.proto +0 -0
- {imbot_sdk_python-0.1.0 → imbot_sdk_python-0.1.1}/requirements.txt +0 -0
- {imbot_sdk_python-0.1.0 → imbot_sdk_python-0.1.1}/setup.cfg +0 -0
|
@@ -4,6 +4,13 @@ All notable changes to this project are documented here. The format follows
|
|
|
4
4
|
[Keep a Changelog](https://keepachangelog.com/), and the project adheres to
|
|
5
5
|
[Semantic Versioning](https://semver.org/).
|
|
6
6
|
|
|
7
|
+
## [0.1.1] - 2026-06-25
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
|
|
11
|
+
- Documentation is now bilingual: English `README.md` / `docs/*.md` with Chinese
|
|
12
|
+
`README.zh-CN.md` / `docs/*.zh-CN.md`, linked via a language switcher.
|
|
13
|
+
|
|
7
14
|
## [0.1.0] - 2026-06-25
|
|
8
15
|
|
|
9
16
|
### Added
|
|
@@ -24,4 +31,5 @@ All notable changes to this project are documented here. The format follows
|
|
|
24
31
|
text, recall info, merge, thumbnail-packed image, snapshot-packed video) with
|
|
25
32
|
an `UnknownMessage` fallback.
|
|
26
33
|
|
|
34
|
+
[0.1.1]: https://github.com/juggleim/imbot-sdk-python/releases/tag/v0.1.1
|
|
27
35
|
[0.1.0]: https://github.com/juggleim/imbot-sdk-python/releases/tag/v0.1.0
|
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: imbot-sdk-python
|
|
3
|
+
Version: 0.1.1
|
|
4
|
+
Summary: JuggleIM Python Bot SDK — WebSocket long-connection IM client for bots and server-side agents
|
|
5
|
+
Author-email: Tyler <tyler@juggle.im>
|
|
6
|
+
Maintainer-email: Tyler <tyler@juggle.im>
|
|
7
|
+
License-Expression: Apache-2.0
|
|
8
|
+
Project-URL: Homepage, https://github.com/juggleim/imbot-sdk-python
|
|
9
|
+
Project-URL: Repository, https://github.com/juggleim/imbot-sdk-python
|
|
10
|
+
Project-URL: Issues, https://github.com/juggleim/imbot-sdk-python/issues
|
|
11
|
+
Project-URL: Documentation, https://github.com/juggleim/imbot-sdk-python#readme
|
|
12
|
+
Keywords: juggleim,im,instant-messaging,chat,bot,websocket,sdk
|
|
13
|
+
Classifier: Development Status :: 3 - Alpha
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
23
|
+
Classifier: Topic :: Communications :: Chat
|
|
24
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
25
|
+
Requires-Python: >=3.8
|
|
26
|
+
Description-Content-Type: text/markdown
|
|
27
|
+
License-File: LICENSE
|
|
28
|
+
Requires-Dist: protobuf>=5.0
|
|
29
|
+
Requires-Dist: websocket-client>=1.6
|
|
30
|
+
Provides-Extra: dev
|
|
31
|
+
Requires-Dist: build; extra == "dev"
|
|
32
|
+
Requires-Dist: twine; extra == "dev"
|
|
33
|
+
Dynamic: license-file
|
|
34
|
+
|
|
35
|
+
# imbot-sdk-python
|
|
36
|
+
|
|
37
|
+
**English** | [简体中文](README.zh-CN.md)
|
|
38
|
+
|
|
39
|
+
[](https://pypi.org/project/imbot-sdk-python/)
|
|
40
|
+
[](https://pypi.org/project/imbot-sdk-python/)
|
|
41
|
+
[](https://github.com/juggleim/imbot-sdk-python/blob/main/LICENSE)
|
|
42
|
+
|
|
43
|
+
`imbot-sdk-python` is the JuggleIM Python SDK. It keeps a long-lived WebSocket
|
|
44
|
+
connection to the IM service, making it a good fit for bots, server-side message
|
|
45
|
+
agents, or any Python program that needs to actively send and receive messages.
|
|
46
|
+
It covers connection management, messaging, conversation queries, history,
|
|
47
|
+
chatrooms, user status, RTC rooms and file credential queries.
|
|
48
|
+
|
|
49
|
+
- Source: <https://github.com/juggleim/imbot-sdk-python>
|
|
50
|
+
- Distribution name: `imbot-sdk-python`; import name: `import imbot_sdk`
|
|
51
|
+
|
|
52
|
+
## Installation
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
pip install imbot-sdk-python
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Dependencies (`protobuf>=5.0`, `websocket-client>=1.6`) are installed
|
|
59
|
+
automatically. Python 3.8+.
|
|
60
|
+
|
|
61
|
+
Install from source:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
git clone https://github.com/juggleim/imbot-sdk-python.git
|
|
65
|
+
cd imbot-sdk-python
|
|
66
|
+
pip install .
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Test environment
|
|
70
|
+
|
|
71
|
+
| Item | Value |
|
|
72
|
+
| --- | --- |
|
|
73
|
+
| Server API | `http://127.0.0.1` |
|
|
74
|
+
| WebSocket | `wss://127.0.0.1` |
|
|
75
|
+
| AppKey | `AppKey` |
|
|
76
|
+
|
|
77
|
+
> A user token is issued by your JuggleIM app server / console using your AppKey
|
|
78
|
+
> + AppSecret via the Server API. The SDK itself only establishes the
|
|
79
|
+
> connection and sends/receives messages.
|
|
80
|
+
|
|
81
|
+
## Feature overview
|
|
82
|
+
|
|
83
|
+
- Connection management: `connect`, `disconnect`, `logout`, heartbeat keep-alive,
|
|
84
|
+
automatic reconnect.
|
|
85
|
+
- Messaging: send/receive for private, group, chatroom and public-channel
|
|
86
|
+
conversations.
|
|
87
|
+
- Message management: history query, recall, modify, mark-read, search, top
|
|
88
|
+
messages.
|
|
89
|
+
- Conversation management: list, unread count, top, mute, tags.
|
|
90
|
+
- User & group info: user profile, friend profile, group info, online-status
|
|
91
|
+
subscription.
|
|
92
|
+
- Chatroom: join/quit, chatroom messages, attribute sync.
|
|
93
|
+
- RTC: create / join / query / quit RTC rooms.
|
|
94
|
+
- File: credential query via `get_file_cred`.
|
|
95
|
+
|
|
96
|
+
## Quick start
|
|
97
|
+
|
|
98
|
+
### 1. Create a client
|
|
99
|
+
|
|
100
|
+
```python
|
|
101
|
+
from imbot_sdk import ImBotClient
|
|
102
|
+
|
|
103
|
+
client = ImBotClient("wss://127.0.0.1", "your-appkey")
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Notes:
|
|
107
|
+
|
|
108
|
+
- Pass the base `address`; the SDK appends the path automatically to form
|
|
109
|
+
`ws://host/imbot` or `wss://host/imbot`.
|
|
110
|
+
- `client.platform` defaults to `"Bot"`.
|
|
111
|
+
- `client.auto_reconnect` defaults to `True`.
|
|
112
|
+
|
|
113
|
+
### 2. Connect
|
|
114
|
+
|
|
115
|
+
```python
|
|
116
|
+
code, ack = client.connect("your-token")
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Notes:
|
|
120
|
+
|
|
121
|
+
- On success `code == ClientErrorCode.SUCCESS`.
|
|
122
|
+
- After success `ack.userId` is written to `client.user_id`.
|
|
123
|
+
- `connect` may only be called while disconnected; a repeated connect returns
|
|
124
|
+
`ClientErrorCode.CONNECT_EXISTED`.
|
|
125
|
+
- After an explicit `disconnect()` or `logout()`, auto-reconnect stops.
|
|
126
|
+
|
|
127
|
+
### 3. Two ways to receive messages
|
|
128
|
+
|
|
129
|
+
Prefer the high-level listener (you receive a decoded `Message`):
|
|
130
|
+
|
|
131
|
+
```python
|
|
132
|
+
from imbot_sdk import MessageListener, messages
|
|
133
|
+
|
|
134
|
+
class MyListener(MessageListener):
|
|
135
|
+
def on_message_receive(self, msg):
|
|
136
|
+
if isinstance(msg.msg_content, messages.TextMessage):
|
|
137
|
+
print("text:", msg.msg_content.content)
|
|
138
|
+
|
|
139
|
+
client.add_message_listener(MyListener())
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
If you want the raw protobuf payloads:
|
|
143
|
+
|
|
144
|
+
```python
|
|
145
|
+
client.on_message_callback = lambda down_msg: print(down_msg)
|
|
146
|
+
client.on_stream_msg_callback = lambda stream_msg: print(stream_msg)
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### 4. Send a message
|
|
150
|
+
|
|
151
|
+
```python
|
|
152
|
+
from imbot_sdk import Conversation, messages
|
|
153
|
+
from imbot_sdk.pb import appmessages_pb2 as pb
|
|
154
|
+
|
|
155
|
+
text = messages.TextMessage("hello from imbot-sdk-python")
|
|
156
|
+
up = client.build_up_msg(text, client_uid="bot-1")
|
|
157
|
+
|
|
158
|
+
conv = Conversation(conversation_type=pb.Private, conversation="target-user-id")
|
|
159
|
+
code, ack = client.send_message(conv, up)
|
|
160
|
+
# ack.msgId / ack.msgSeqNo carry the server's acknowledgement
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
`build_up_msg` encodes a content model into `UpMsg.msgType / msgContent /
|
|
164
|
+
flags`; you can also construct a `pb.UpMsg` directly.
|
|
165
|
+
|
|
166
|
+
## Full example: connect, listen, echo
|
|
167
|
+
|
|
168
|
+
```python
|
|
169
|
+
import time
|
|
170
|
+
from imbot_sdk import ImBotClient, Conversation, MessageListener, ClientErrorCode, messages
|
|
171
|
+
from imbot_sdk.pb import appmessages_pb2 as pb
|
|
172
|
+
|
|
173
|
+
class Echo(MessageListener):
|
|
174
|
+
def __init__(self, client):
|
|
175
|
+
self.client = client
|
|
176
|
+
def on_message_receive(self, msg):
|
|
177
|
+
c = msg.msg_content
|
|
178
|
+
if isinstance(c, messages.TextMessage) and msg.sender_id != self.client.user_id:
|
|
179
|
+
up = self.client.build_up_msg(messages.TextMessage("echo: " + c.content),
|
|
180
|
+
client_uid="echo-%d" % time.time_ns())
|
|
181
|
+
self.client.send_message(msg.conversation, up)
|
|
182
|
+
|
|
183
|
+
client = ImBotClient("wss://127.0.0.1", "AppKey")
|
|
184
|
+
client.add_message_listener(Echo(client))
|
|
185
|
+
|
|
186
|
+
code, ack = client.connect("your-token")
|
|
187
|
+
assert code == ClientErrorCode.SUCCESS
|
|
188
|
+
print("connected:", ack.userId)
|
|
189
|
+
|
|
190
|
+
# Proactively send a private message to a user
|
|
191
|
+
up = client.build_up_msg(messages.TextMessage("hi"), client_uid="greet-1")
|
|
192
|
+
client.send_message(Conversation(conversation_type=pb.Private, conversation="target-user-id"), up)
|
|
193
|
+
|
|
194
|
+
try:
|
|
195
|
+
while True:
|
|
196
|
+
time.sleep(1)
|
|
197
|
+
except KeyboardInterrupt:
|
|
198
|
+
client.disconnect()
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
A runnable version lives in [`examples/echo_bot.py`](examples/echo_bot.py). The
|
|
202
|
+
recommended way is `.env` + the launch script:
|
|
203
|
+
|
|
204
|
+
```bash
|
|
205
|
+
cp examples/.env.example examples/.env
|
|
206
|
+
# edit examples/.env, at least set IMBOT_TOKEN (IMBOT_TARGET optional)
|
|
207
|
+
bash examples/run.sh
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
`run.sh` loads `examples/.env` and starts the echo bot; extra arguments are
|
|
211
|
+
passed through (e.g. `bash examples/run.sh --target some-user-id`). You can also
|
|
212
|
+
skip the script and pass args / export env vars directly:
|
|
213
|
+
|
|
214
|
+
```bash
|
|
215
|
+
python examples/echo_bot.py --token <your-token> --target <target-user-id>
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
Configuration (env vars / `.env`):
|
|
219
|
+
|
|
220
|
+
| Variable | Description | Required |
|
|
221
|
+
| --- | --- | --- |
|
|
222
|
+
| `IMBOT_TOKEN` | User token | Yes |
|
|
223
|
+
| `IMBOT_TARGET` | Target user id to greet on startup | No |
|
|
224
|
+
| `IMBOT_ADDRESS` | WebSocket base address | No |
|
|
225
|
+
| `IMBOT_APPKEY` | App AppKey | No |
|
|
226
|
+
|
|
227
|
+
Additional notes:
|
|
228
|
+
|
|
229
|
+
- Use `pb.Private` for private chats, `pb.Group` for groups, `pb.Chatroom` for
|
|
230
|
+
chatrooms, `pb.PublicChannel` for public channels.
|
|
231
|
+
- Chatroom messages can also be sent via `client.send_chatroom_msg(chatroom_id, up_msg)`.
|
|
232
|
+
- A received `msg.msg_content` is already decoded by content type, so you can
|
|
233
|
+
`isinstance`-check it directly.
|
|
234
|
+
|
|
235
|
+
## Message types
|
|
236
|
+
|
|
237
|
+
Built-in content models live in `imbot_sdk.messages`:
|
|
238
|
+
|
|
239
|
+
| Type | Identifier | Class |
|
|
240
|
+
| --- | --- | --- |
|
|
241
|
+
| Text | `jg:text` | `TextMessage` |
|
|
242
|
+
| Image | `jg:img` | `ImageMessage` |
|
|
243
|
+
| File | `jg:file` | `FileMessage` |
|
|
244
|
+
| Video | `jg:video` | `VideoMessage` |
|
|
245
|
+
| Voice | `jg:voice` | `VoiceMessage` |
|
|
246
|
+
| Stream text | `jg:streamtext` | `StreamTextMessage` |
|
|
247
|
+
| Recall notice | `jg:recallinfo` | `RecallInfoMessage` |
|
|
248
|
+
| Merged message | `jg:merge` | `MergeMessage` |
|
|
249
|
+
| Thumbnail-packed image | `jg:tpimg` | `ThumbnailPackedImageMessage` |
|
|
250
|
+
| Snapshot-packed video | `jg:spvideo` | `SnapshotPackedVideoMessage` |
|
|
251
|
+
|
|
252
|
+
For content types that are not built in, the SDK falls back to
|
|
253
|
+
`messages.UnknownMessage`. The JSON encode/decode fields of these models are
|
|
254
|
+
stable, so messages interoperate with the other JuggleIM client SDKs.
|
|
255
|
+
|
|
256
|
+
## Common APIs
|
|
257
|
+
|
|
258
|
+
> See [`docs/API.md`](docs/API.md) for the full method list. Naming follows
|
|
259
|
+
> Python conventions (snake_case).
|
|
260
|
+
|
|
261
|
+
### Connection & state
|
|
262
|
+
|
|
263
|
+
`connect(token)`, `reconnect()`, `disconnect()`, `logout()`, `ping()`,
|
|
264
|
+
`add_connection_status_change_listener(listener)`
|
|
265
|
+
|
|
266
|
+
### Messages
|
|
267
|
+
|
|
268
|
+
`send_message(conversation, up_msg)`, `qry_history_msgs(req)`, `recall_msg(req)`,
|
|
269
|
+
`modify_msg(req)`, `mark_read_msg(req)`, `msg_search(req)`,
|
|
270
|
+
`msg_global_search(req)`, `set_top_msg(req)`, `del_top_msg(req)`
|
|
271
|
+
|
|
272
|
+
### Conversations
|
|
273
|
+
|
|
274
|
+
`get_conversation(req)`, `get_conversations(req)`, `sync_conversations(req)`,
|
|
275
|
+
`clear_unread_count(req)`, `set_conversation_top(req)`, `set_mute(req)`,
|
|
276
|
+
`delete_conversations(req)`
|
|
277
|
+
|
|
278
|
+
### Users, groups, status
|
|
279
|
+
|
|
280
|
+
`fetch_user_info(user_id)`, `fetch_group_info(group_id)`,
|
|
281
|
+
`fetch_friend_info(friend_user_id)`, `get_user_status(req)`,
|
|
282
|
+
`subscribe_user_status(req)`, `unsubscribe_user_status(req)`
|
|
283
|
+
|
|
284
|
+
### Chatroom
|
|
285
|
+
|
|
286
|
+
`join_chatroom(chatroom_id)`, `quit_chatroom(chatroom_id)`,
|
|
287
|
+
`send_chatroom_msg(chatroom_id, up_msg)`, `set_attributes(chatroom_id, attributes)`,
|
|
288
|
+
`remove_attributes(chatroom_id, keys)`
|
|
289
|
+
|
|
290
|
+
### RTC
|
|
291
|
+
|
|
292
|
+
`create_rtc_room(req)`, `join_rtc_room(req)`, `qry_rtc_room(room_id)`,
|
|
293
|
+
`quit_rtc_room(room_id)`, `rtc_invite(req)`
|
|
294
|
+
|
|
295
|
+
### File
|
|
296
|
+
|
|
297
|
+
`get_file_cred(req)`
|
|
298
|
+
|
|
299
|
+
> The SDK provides file credential queries; the actual file upload/download flow
|
|
300
|
+
> must be handled by your application against your storage service.
|
|
301
|
+
|
|
302
|
+
## Usage notes
|
|
303
|
+
|
|
304
|
+
- `publish` and `query` both require the connection state to be `CONNECTED`,
|
|
305
|
+
otherwise they return `ClientErrorCode.CONNECT_CLOSED`.
|
|
306
|
+
- Sends and queries wait up to 10 seconds for an ACK, returning
|
|
307
|
+
`ClientErrorCode.SEND_TIMEOUT` / `ClientErrorCode.QUERY_TIMEOUT` on timeout.
|
|
308
|
+
- The SDK handles heartbeats automatically; if no downstream data arrives for
|
|
309
|
+
more than two heartbeat windows (~20s), it disconnects and tries to reconnect.
|
|
310
|
+
- Message listener callbacks run on internal threads — avoid long blocking work,
|
|
311
|
+
and hand off to a worker queue if needed.
|
|
312
|
+
- Image / file / voice / video content models only encode/decode content; they
|
|
313
|
+
do not upload the underlying files.
|
|
314
|
+
|
|
315
|
+
## Regenerating protobuf
|
|
316
|
+
|
|
317
|
+
The `.proto` sources live in [`proto/`](proto/). Regenerate after editing:
|
|
318
|
+
|
|
319
|
+
```bash
|
|
320
|
+
bash proto/gen.sh
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
## Module layout
|
|
324
|
+
|
|
325
|
+
| Module | Description |
|
|
326
|
+
| --- | --- |
|
|
327
|
+
| `imbot_sdk.ImBotClient` | Main client entry point |
|
|
328
|
+
| `imbot_sdk.ClientErrorCode` / `ConnectState` | Error codes and connection state |
|
|
329
|
+
| `imbot_sdk.models` | Domain models (`Conversation` / `Message` / `UserInfo` …) |
|
|
330
|
+
| `imbot_sdk.messages` | Message content models |
|
|
331
|
+
| `imbot_sdk.pb` | Protobuf types (`appmessages_pb2` / `connect_pb2` / `chatroom_pb2` / `rtcroom_pb2`) |
|
|
332
|
+
|
|
333
|
+
## License
|
|
334
|
+
|
|
335
|
+
[LICENSE](LICENSE) (Apache-2.0)
|
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
# imbot-sdk-python
|
|
2
|
+
|
|
3
|
+
**English** | [简体中文](README.zh-CN.md)
|
|
4
|
+
|
|
5
|
+
[](https://pypi.org/project/imbot-sdk-python/)
|
|
6
|
+
[](https://pypi.org/project/imbot-sdk-python/)
|
|
7
|
+
[](https://github.com/juggleim/imbot-sdk-python/blob/main/LICENSE)
|
|
8
|
+
|
|
9
|
+
`imbot-sdk-python` is the JuggleIM Python SDK. It keeps a long-lived WebSocket
|
|
10
|
+
connection to the IM service, making it a good fit for bots, server-side message
|
|
11
|
+
agents, or any Python program that needs to actively send and receive messages.
|
|
12
|
+
It covers connection management, messaging, conversation queries, history,
|
|
13
|
+
chatrooms, user status, RTC rooms and file credential queries.
|
|
14
|
+
|
|
15
|
+
- Source: <https://github.com/juggleim/imbot-sdk-python>
|
|
16
|
+
- Distribution name: `imbot-sdk-python`; import name: `import imbot_sdk`
|
|
17
|
+
|
|
18
|
+
## Installation
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
pip install imbot-sdk-python
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Dependencies (`protobuf>=5.0`, `websocket-client>=1.6`) are installed
|
|
25
|
+
automatically. Python 3.8+.
|
|
26
|
+
|
|
27
|
+
Install from source:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
git clone https://github.com/juggleim/imbot-sdk-python.git
|
|
31
|
+
cd imbot-sdk-python
|
|
32
|
+
pip install .
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Test environment
|
|
36
|
+
|
|
37
|
+
| Item | Value |
|
|
38
|
+
| --- | --- |
|
|
39
|
+
| Server API | `http://127.0.0.1` |
|
|
40
|
+
| WebSocket | `wss://127.0.0.1` |
|
|
41
|
+
| AppKey | `AppKey` |
|
|
42
|
+
|
|
43
|
+
> A user token is issued by your JuggleIM app server / console using your AppKey
|
|
44
|
+
> + AppSecret via the Server API. The SDK itself only establishes the
|
|
45
|
+
> connection and sends/receives messages.
|
|
46
|
+
|
|
47
|
+
## Feature overview
|
|
48
|
+
|
|
49
|
+
- Connection management: `connect`, `disconnect`, `logout`, heartbeat keep-alive,
|
|
50
|
+
automatic reconnect.
|
|
51
|
+
- Messaging: send/receive for private, group, chatroom and public-channel
|
|
52
|
+
conversations.
|
|
53
|
+
- Message management: history query, recall, modify, mark-read, search, top
|
|
54
|
+
messages.
|
|
55
|
+
- Conversation management: list, unread count, top, mute, tags.
|
|
56
|
+
- User & group info: user profile, friend profile, group info, online-status
|
|
57
|
+
subscription.
|
|
58
|
+
- Chatroom: join/quit, chatroom messages, attribute sync.
|
|
59
|
+
- RTC: create / join / query / quit RTC rooms.
|
|
60
|
+
- File: credential query via `get_file_cred`.
|
|
61
|
+
|
|
62
|
+
## Quick start
|
|
63
|
+
|
|
64
|
+
### 1. Create a client
|
|
65
|
+
|
|
66
|
+
```python
|
|
67
|
+
from imbot_sdk import ImBotClient
|
|
68
|
+
|
|
69
|
+
client = ImBotClient("wss://127.0.0.1", "your-appkey")
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Notes:
|
|
73
|
+
|
|
74
|
+
- Pass the base `address`; the SDK appends the path automatically to form
|
|
75
|
+
`ws://host/imbot` or `wss://host/imbot`.
|
|
76
|
+
- `client.platform` defaults to `"Bot"`.
|
|
77
|
+
- `client.auto_reconnect` defaults to `True`.
|
|
78
|
+
|
|
79
|
+
### 2. Connect
|
|
80
|
+
|
|
81
|
+
```python
|
|
82
|
+
code, ack = client.connect("your-token")
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Notes:
|
|
86
|
+
|
|
87
|
+
- On success `code == ClientErrorCode.SUCCESS`.
|
|
88
|
+
- After success `ack.userId` is written to `client.user_id`.
|
|
89
|
+
- `connect` may only be called while disconnected; a repeated connect returns
|
|
90
|
+
`ClientErrorCode.CONNECT_EXISTED`.
|
|
91
|
+
- After an explicit `disconnect()` or `logout()`, auto-reconnect stops.
|
|
92
|
+
|
|
93
|
+
### 3. Two ways to receive messages
|
|
94
|
+
|
|
95
|
+
Prefer the high-level listener (you receive a decoded `Message`):
|
|
96
|
+
|
|
97
|
+
```python
|
|
98
|
+
from imbot_sdk import MessageListener, messages
|
|
99
|
+
|
|
100
|
+
class MyListener(MessageListener):
|
|
101
|
+
def on_message_receive(self, msg):
|
|
102
|
+
if isinstance(msg.msg_content, messages.TextMessage):
|
|
103
|
+
print("text:", msg.msg_content.content)
|
|
104
|
+
|
|
105
|
+
client.add_message_listener(MyListener())
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
If you want the raw protobuf payloads:
|
|
109
|
+
|
|
110
|
+
```python
|
|
111
|
+
client.on_message_callback = lambda down_msg: print(down_msg)
|
|
112
|
+
client.on_stream_msg_callback = lambda stream_msg: print(stream_msg)
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### 4. Send a message
|
|
116
|
+
|
|
117
|
+
```python
|
|
118
|
+
from imbot_sdk import Conversation, messages
|
|
119
|
+
from imbot_sdk.pb import appmessages_pb2 as pb
|
|
120
|
+
|
|
121
|
+
text = messages.TextMessage("hello from imbot-sdk-python")
|
|
122
|
+
up = client.build_up_msg(text, client_uid="bot-1")
|
|
123
|
+
|
|
124
|
+
conv = Conversation(conversation_type=pb.Private, conversation="target-user-id")
|
|
125
|
+
code, ack = client.send_message(conv, up)
|
|
126
|
+
# ack.msgId / ack.msgSeqNo carry the server's acknowledgement
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
`build_up_msg` encodes a content model into `UpMsg.msgType / msgContent /
|
|
130
|
+
flags`; you can also construct a `pb.UpMsg` directly.
|
|
131
|
+
|
|
132
|
+
## Full example: connect, listen, echo
|
|
133
|
+
|
|
134
|
+
```python
|
|
135
|
+
import time
|
|
136
|
+
from imbot_sdk import ImBotClient, Conversation, MessageListener, ClientErrorCode, messages
|
|
137
|
+
from imbot_sdk.pb import appmessages_pb2 as pb
|
|
138
|
+
|
|
139
|
+
class Echo(MessageListener):
|
|
140
|
+
def __init__(self, client):
|
|
141
|
+
self.client = client
|
|
142
|
+
def on_message_receive(self, msg):
|
|
143
|
+
c = msg.msg_content
|
|
144
|
+
if isinstance(c, messages.TextMessage) and msg.sender_id != self.client.user_id:
|
|
145
|
+
up = self.client.build_up_msg(messages.TextMessage("echo: " + c.content),
|
|
146
|
+
client_uid="echo-%d" % time.time_ns())
|
|
147
|
+
self.client.send_message(msg.conversation, up)
|
|
148
|
+
|
|
149
|
+
client = ImBotClient("wss://127.0.0.1", "AppKey")
|
|
150
|
+
client.add_message_listener(Echo(client))
|
|
151
|
+
|
|
152
|
+
code, ack = client.connect("your-token")
|
|
153
|
+
assert code == ClientErrorCode.SUCCESS
|
|
154
|
+
print("connected:", ack.userId)
|
|
155
|
+
|
|
156
|
+
# Proactively send a private message to a user
|
|
157
|
+
up = client.build_up_msg(messages.TextMessage("hi"), client_uid="greet-1")
|
|
158
|
+
client.send_message(Conversation(conversation_type=pb.Private, conversation="target-user-id"), up)
|
|
159
|
+
|
|
160
|
+
try:
|
|
161
|
+
while True:
|
|
162
|
+
time.sleep(1)
|
|
163
|
+
except KeyboardInterrupt:
|
|
164
|
+
client.disconnect()
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
A runnable version lives in [`examples/echo_bot.py`](examples/echo_bot.py). The
|
|
168
|
+
recommended way is `.env` + the launch script:
|
|
169
|
+
|
|
170
|
+
```bash
|
|
171
|
+
cp examples/.env.example examples/.env
|
|
172
|
+
# edit examples/.env, at least set IMBOT_TOKEN (IMBOT_TARGET optional)
|
|
173
|
+
bash examples/run.sh
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
`run.sh` loads `examples/.env` and starts the echo bot; extra arguments are
|
|
177
|
+
passed through (e.g. `bash examples/run.sh --target some-user-id`). You can also
|
|
178
|
+
skip the script and pass args / export env vars directly:
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
python examples/echo_bot.py --token <your-token> --target <target-user-id>
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
Configuration (env vars / `.env`):
|
|
185
|
+
|
|
186
|
+
| Variable | Description | Required |
|
|
187
|
+
| --- | --- | --- |
|
|
188
|
+
| `IMBOT_TOKEN` | User token | Yes |
|
|
189
|
+
| `IMBOT_TARGET` | Target user id to greet on startup | No |
|
|
190
|
+
| `IMBOT_ADDRESS` | WebSocket base address | No |
|
|
191
|
+
| `IMBOT_APPKEY` | App AppKey | No |
|
|
192
|
+
|
|
193
|
+
Additional notes:
|
|
194
|
+
|
|
195
|
+
- Use `pb.Private` for private chats, `pb.Group` for groups, `pb.Chatroom` for
|
|
196
|
+
chatrooms, `pb.PublicChannel` for public channels.
|
|
197
|
+
- Chatroom messages can also be sent via `client.send_chatroom_msg(chatroom_id, up_msg)`.
|
|
198
|
+
- A received `msg.msg_content` is already decoded by content type, so you can
|
|
199
|
+
`isinstance`-check it directly.
|
|
200
|
+
|
|
201
|
+
## Message types
|
|
202
|
+
|
|
203
|
+
Built-in content models live in `imbot_sdk.messages`:
|
|
204
|
+
|
|
205
|
+
| Type | Identifier | Class |
|
|
206
|
+
| --- | --- | --- |
|
|
207
|
+
| Text | `jg:text` | `TextMessage` |
|
|
208
|
+
| Image | `jg:img` | `ImageMessage` |
|
|
209
|
+
| File | `jg:file` | `FileMessage` |
|
|
210
|
+
| Video | `jg:video` | `VideoMessage` |
|
|
211
|
+
| Voice | `jg:voice` | `VoiceMessage` |
|
|
212
|
+
| Stream text | `jg:streamtext` | `StreamTextMessage` |
|
|
213
|
+
| Recall notice | `jg:recallinfo` | `RecallInfoMessage` |
|
|
214
|
+
| Merged message | `jg:merge` | `MergeMessage` |
|
|
215
|
+
| Thumbnail-packed image | `jg:tpimg` | `ThumbnailPackedImageMessage` |
|
|
216
|
+
| Snapshot-packed video | `jg:spvideo` | `SnapshotPackedVideoMessage` |
|
|
217
|
+
|
|
218
|
+
For content types that are not built in, the SDK falls back to
|
|
219
|
+
`messages.UnknownMessage`. The JSON encode/decode fields of these models are
|
|
220
|
+
stable, so messages interoperate with the other JuggleIM client SDKs.
|
|
221
|
+
|
|
222
|
+
## Common APIs
|
|
223
|
+
|
|
224
|
+
> See [`docs/API.md`](docs/API.md) for the full method list. Naming follows
|
|
225
|
+
> Python conventions (snake_case).
|
|
226
|
+
|
|
227
|
+
### Connection & state
|
|
228
|
+
|
|
229
|
+
`connect(token)`, `reconnect()`, `disconnect()`, `logout()`, `ping()`,
|
|
230
|
+
`add_connection_status_change_listener(listener)`
|
|
231
|
+
|
|
232
|
+
### Messages
|
|
233
|
+
|
|
234
|
+
`send_message(conversation, up_msg)`, `qry_history_msgs(req)`, `recall_msg(req)`,
|
|
235
|
+
`modify_msg(req)`, `mark_read_msg(req)`, `msg_search(req)`,
|
|
236
|
+
`msg_global_search(req)`, `set_top_msg(req)`, `del_top_msg(req)`
|
|
237
|
+
|
|
238
|
+
### Conversations
|
|
239
|
+
|
|
240
|
+
`get_conversation(req)`, `get_conversations(req)`, `sync_conversations(req)`,
|
|
241
|
+
`clear_unread_count(req)`, `set_conversation_top(req)`, `set_mute(req)`,
|
|
242
|
+
`delete_conversations(req)`
|
|
243
|
+
|
|
244
|
+
### Users, groups, status
|
|
245
|
+
|
|
246
|
+
`fetch_user_info(user_id)`, `fetch_group_info(group_id)`,
|
|
247
|
+
`fetch_friend_info(friend_user_id)`, `get_user_status(req)`,
|
|
248
|
+
`subscribe_user_status(req)`, `unsubscribe_user_status(req)`
|
|
249
|
+
|
|
250
|
+
### Chatroom
|
|
251
|
+
|
|
252
|
+
`join_chatroom(chatroom_id)`, `quit_chatroom(chatroom_id)`,
|
|
253
|
+
`send_chatroom_msg(chatroom_id, up_msg)`, `set_attributes(chatroom_id, attributes)`,
|
|
254
|
+
`remove_attributes(chatroom_id, keys)`
|
|
255
|
+
|
|
256
|
+
### RTC
|
|
257
|
+
|
|
258
|
+
`create_rtc_room(req)`, `join_rtc_room(req)`, `qry_rtc_room(room_id)`,
|
|
259
|
+
`quit_rtc_room(room_id)`, `rtc_invite(req)`
|
|
260
|
+
|
|
261
|
+
### File
|
|
262
|
+
|
|
263
|
+
`get_file_cred(req)`
|
|
264
|
+
|
|
265
|
+
> The SDK provides file credential queries; the actual file upload/download flow
|
|
266
|
+
> must be handled by your application against your storage service.
|
|
267
|
+
|
|
268
|
+
## Usage notes
|
|
269
|
+
|
|
270
|
+
- `publish` and `query` both require the connection state to be `CONNECTED`,
|
|
271
|
+
otherwise they return `ClientErrorCode.CONNECT_CLOSED`.
|
|
272
|
+
- Sends and queries wait up to 10 seconds for an ACK, returning
|
|
273
|
+
`ClientErrorCode.SEND_TIMEOUT` / `ClientErrorCode.QUERY_TIMEOUT` on timeout.
|
|
274
|
+
- The SDK handles heartbeats automatically; if no downstream data arrives for
|
|
275
|
+
more than two heartbeat windows (~20s), it disconnects and tries to reconnect.
|
|
276
|
+
- Message listener callbacks run on internal threads — avoid long blocking work,
|
|
277
|
+
and hand off to a worker queue if needed.
|
|
278
|
+
- Image / file / voice / video content models only encode/decode content; they
|
|
279
|
+
do not upload the underlying files.
|
|
280
|
+
|
|
281
|
+
## Regenerating protobuf
|
|
282
|
+
|
|
283
|
+
The `.proto` sources live in [`proto/`](proto/). Regenerate after editing:
|
|
284
|
+
|
|
285
|
+
```bash
|
|
286
|
+
bash proto/gen.sh
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
## Module layout
|
|
290
|
+
|
|
291
|
+
| Module | Description |
|
|
292
|
+
| --- | --- |
|
|
293
|
+
| `imbot_sdk.ImBotClient` | Main client entry point |
|
|
294
|
+
| `imbot_sdk.ClientErrorCode` / `ConnectState` | Error codes and connection state |
|
|
295
|
+
| `imbot_sdk.models` | Domain models (`Conversation` / `Message` / `UserInfo` …) |
|
|
296
|
+
| `imbot_sdk.messages` | Message content models |
|
|
297
|
+
| `imbot_sdk.pb` | Protobuf types (`appmessages_pb2` / `connect_pb2` / `chatroom_pb2` / `rtcroom_pb2`) |
|
|
298
|
+
|
|
299
|
+
## License
|
|
300
|
+
|
|
301
|
+
[LICENSE](LICENSE) (Apache-2.0)
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# imbot-sdk-python
|
|
2
2
|
|
|
3
|
+
[English](README.md) | **简体中文**
|
|
4
|
+
|
|
3
5
|
[](https://pypi.org/project/imbot-sdk-python/)
|
|
4
6
|
[](https://pypi.org/project/imbot-sdk-python/)
|
|
5
7
|
[](https://github.com/juggleim/imbot-sdk-python/blob/main/LICENSE)
|
|
@@ -199,7 +201,7 @@ python examples/echo_bot.py --token <your-token> --target <target-user-id>
|
|
|
199
201
|
|
|
200
202
|
## 常用 API
|
|
201
203
|
|
|
202
|
-
> 完整方法清单见 [`docs/API.md`](docs/API.md)。命名采用 Python 风格(snake_case)。
|
|
204
|
+
> 完整方法清单见 [`docs/API.zh-CN.md`](docs/API.zh-CN.md)。命名采用 Python 风格(snake_case)。
|
|
203
205
|
|
|
204
206
|
### 连接与状态
|
|
205
207
|
|