imbot-sdk-python 0.1.1__tar.gz → 0.1.2__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.1 → imbot_sdk_python-0.1.2}/CHANGELOG.md +10 -0
- {imbot_sdk_python-0.1.1/imbot_sdk_python.egg-info → imbot_sdk_python-0.1.2}/PKG-INFO +32 -1
- {imbot_sdk_python-0.1.1 → imbot_sdk_python-0.1.2}/README.md +31 -0
- {imbot_sdk_python-0.1.1 → imbot_sdk_python-0.1.2}/README.zh-CN.md +29 -0
- {imbot_sdk_python-0.1.1 → imbot_sdk_python-0.1.2}/docs/PROTOCOL.md +21 -0
- {imbot_sdk_python-0.1.1 → imbot_sdk_python-0.1.2}/docs/PROTOCOL.zh-CN.md +19 -0
- imbot_sdk_python-0.1.2/examples/register_bot.py +125 -0
- {imbot_sdk_python-0.1.1 → imbot_sdk_python-0.1.2}/imbot_sdk/__init__.py +1 -1
- {imbot_sdk_python-0.1.1 → imbot_sdk_python-0.1.2/imbot_sdk_python.egg-info}/PKG-INFO +32 -1
- {imbot_sdk_python-0.1.1 → imbot_sdk_python-0.1.2}/imbot_sdk_python.egg-info/SOURCES.txt +1 -0
- {imbot_sdk_python-0.1.1 → imbot_sdk_python-0.1.2}/pyproject.toml +1 -1
- {imbot_sdk_python-0.1.1 → imbot_sdk_python-0.1.2}/LICENSE +0 -0
- {imbot_sdk_python-0.1.1 → imbot_sdk_python-0.1.2}/MANIFEST.in +0 -0
- {imbot_sdk_python-0.1.1 → imbot_sdk_python-0.1.2}/docs/API.md +0 -0
- {imbot_sdk_python-0.1.1 → imbot_sdk_python-0.1.2}/docs/API.zh-CN.md +0 -0
- {imbot_sdk_python-0.1.1 → imbot_sdk_python-0.1.2}/examples/.env.example +0 -0
- {imbot_sdk_python-0.1.1 → imbot_sdk_python-0.1.2}/examples/echo_bot.py +0 -0
- {imbot_sdk_python-0.1.1 → imbot_sdk_python-0.1.2}/examples/quickstart.py +0 -0
- {imbot_sdk_python-0.1.1 → imbot_sdk_python-0.1.2}/examples/run.sh +0 -0
- {imbot_sdk_python-0.1.1 → imbot_sdk_python-0.1.2}/imbot_sdk/client.py +0 -0
- {imbot_sdk_python-0.1.1 → imbot_sdk_python-0.1.2}/imbot_sdk/consts.py +0 -0
- {imbot_sdk_python-0.1.1 → imbot_sdk_python-0.1.2}/imbot_sdk/data_accessor.py +0 -0
- {imbot_sdk_python-0.1.1 → imbot_sdk_python-0.1.2}/imbot_sdk/listeners.py +0 -0
- {imbot_sdk_python-0.1.1 → imbot_sdk_python-0.1.2}/imbot_sdk/messages/__init__.py +0 -0
- {imbot_sdk_python-0.1.1 → imbot_sdk_python-0.1.2}/imbot_sdk/messages/base.py +0 -0
- {imbot_sdk_python-0.1.1 → imbot_sdk_python-0.1.2}/imbot_sdk/messages/contents.py +0 -0
- {imbot_sdk_python-0.1.1 → imbot_sdk_python-0.1.2}/imbot_sdk/models.py +0 -0
- {imbot_sdk_python-0.1.1 → imbot_sdk_python-0.1.2}/imbot_sdk/pb/__init__.py +0 -0
- {imbot_sdk_python-0.1.1 → imbot_sdk_python-0.1.2}/imbot_sdk/pb/appmessages_pb2.py +0 -0
- {imbot_sdk_python-0.1.1 → imbot_sdk_python-0.1.2}/imbot_sdk/pb/chatroom_pb2.py +0 -0
- {imbot_sdk_python-0.1.1 → imbot_sdk_python-0.1.2}/imbot_sdk/pb/connect_pb2.py +0 -0
- {imbot_sdk_python-0.1.1 → imbot_sdk_python-0.1.2}/imbot_sdk/pb/rtcroom_pb2.py +0 -0
- {imbot_sdk_python-0.1.1 → imbot_sdk_python-0.1.2}/imbot_sdk/py.typed +0 -0
- {imbot_sdk_python-0.1.1 → imbot_sdk_python-0.1.2}/imbot_sdk_python.egg-info/dependency_links.txt +0 -0
- {imbot_sdk_python-0.1.1 → imbot_sdk_python-0.1.2}/imbot_sdk_python.egg-info/requires.txt +0 -0
- {imbot_sdk_python-0.1.1 → imbot_sdk_python-0.1.2}/imbot_sdk_python.egg-info/top_level.txt +0 -0
- {imbot_sdk_python-0.1.1 → imbot_sdk_python-0.1.2}/proto/appmessages.proto +0 -0
- {imbot_sdk_python-0.1.1 → imbot_sdk_python-0.1.2}/proto/chatroom.proto +0 -0
- {imbot_sdk_python-0.1.1 → imbot_sdk_python-0.1.2}/proto/connect.proto +0 -0
- {imbot_sdk_python-0.1.1 → imbot_sdk_python-0.1.2}/proto/gen.sh +0 -0
- {imbot_sdk_python-0.1.1 → imbot_sdk_python-0.1.2}/proto/rtcroom.proto +0 -0
- {imbot_sdk_python-0.1.1 → imbot_sdk_python-0.1.2}/requirements.txt +0 -0
- {imbot_sdk_python-0.1.1 → imbot_sdk_python-0.1.2}/setup.cfg +0 -0
|
@@ -4,6 +4,15 @@ 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.2] - 2026-06-26
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- `examples/register_bot.py`: register a bot/user via the Server API and print a
|
|
12
|
+
connection token (standard library only, no hard-coded credentials).
|
|
13
|
+
- Token acquisition documented in the README and protocol docs (Server API
|
|
14
|
+
endpoint, signature auth, response envelope).
|
|
15
|
+
|
|
7
16
|
## [0.1.1] - 2026-06-25
|
|
8
17
|
|
|
9
18
|
### Changed
|
|
@@ -31,5 +40,6 @@ All notable changes to this project are documented here. The format follows
|
|
|
31
40
|
text, recall info, merge, thumbnail-packed image, snapshot-packed video) with
|
|
32
41
|
an `UnknownMessage` fallback.
|
|
33
42
|
|
|
43
|
+
[0.1.2]: https://github.com/juggleim/imbot-sdk-python/releases/tag/v0.1.2
|
|
34
44
|
[0.1.1]: https://github.com/juggleim/imbot-sdk-python/releases/tag/v0.1.1
|
|
35
45
|
[0.1.0]: https://github.com/juggleim/imbot-sdk-python/releases/tag/v0.1.0
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: imbot-sdk-python
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.2
|
|
4
4
|
Summary: JuggleIM Python Bot SDK — WebSocket long-connection IM client for bots and server-side agents
|
|
5
5
|
Author-email: Tyler <tyler@juggle.im>
|
|
6
6
|
Maintainer-email: Tyler <tyler@juggle.im>
|
|
@@ -78,6 +78,37 @@ pip install .
|
|
|
78
78
|
> + AppSecret via the Server API. The SDK itself only establishes the
|
|
79
79
|
> connection and sends/receives messages.
|
|
80
80
|
|
|
81
|
+
## Obtaining a token
|
|
82
|
+
|
|
83
|
+
`connect(token)` needs a per-user token. Tokens are minted by your app server
|
|
84
|
+
through the JuggleIM Server API using your AppKey + AppSecret. Registering a bot
|
|
85
|
+
(or a user) returns a token:
|
|
86
|
+
|
|
87
|
+
- Endpoint: `POST {ServerAPI}/bots/register` (or `/users/register`)
|
|
88
|
+
- Auth headers: `appkey`, `nonce` (random 0-9999), `timestamp` (epoch ms),
|
|
89
|
+
`signature = lowercase_hex( SHA1(AppSecret + nonce + timestamp) )`,
|
|
90
|
+
`Content-Type: application/json`
|
|
91
|
+
- Response: `{"code":0,"msg":"success","data":{"user_id":"...","token":"..."}}`
|
|
92
|
+
|
|
93
|
+
A ready-to-use helper (standard library only, no hard-coded credentials) is
|
|
94
|
+
[`examples/register_bot.py`](examples/register_bot.py):
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
export IMBOT_API_URL="https://api.juggleim.com/apigateway"
|
|
98
|
+
export IMBOT_APPKEY="<your-appkey>"
|
|
99
|
+
export IMBOT_APPSECRET="<your-appsecret>"
|
|
100
|
+
|
|
101
|
+
# register a bot and print its token
|
|
102
|
+
python examples/register_bot.py --bot-id my-bot --nickname "My Bot"
|
|
103
|
+
|
|
104
|
+
# or register a normal user
|
|
105
|
+
python examples/register_bot.py --user --user-id u1 --nickname "User 1"
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
> Keep your AppSecret on the server side — never ship it inside client apps.
|
|
109
|
+
> If the Server API host presents an expired/invalid TLS certificate, pass
|
|
110
|
+
> `--insecure` to bypass verification (use only against endpoints you trust).
|
|
111
|
+
|
|
81
112
|
## Feature overview
|
|
82
113
|
|
|
83
114
|
- Connection management: `connect`, `disconnect`, `logout`, heartbeat keep-alive,
|
|
@@ -44,6 +44,37 @@ pip install .
|
|
|
44
44
|
> + AppSecret via the Server API. The SDK itself only establishes the
|
|
45
45
|
> connection and sends/receives messages.
|
|
46
46
|
|
|
47
|
+
## Obtaining a token
|
|
48
|
+
|
|
49
|
+
`connect(token)` needs a per-user token. Tokens are minted by your app server
|
|
50
|
+
through the JuggleIM Server API using your AppKey + AppSecret. Registering a bot
|
|
51
|
+
(or a user) returns a token:
|
|
52
|
+
|
|
53
|
+
- Endpoint: `POST {ServerAPI}/bots/register` (or `/users/register`)
|
|
54
|
+
- Auth headers: `appkey`, `nonce` (random 0-9999), `timestamp` (epoch ms),
|
|
55
|
+
`signature = lowercase_hex( SHA1(AppSecret + nonce + timestamp) )`,
|
|
56
|
+
`Content-Type: application/json`
|
|
57
|
+
- Response: `{"code":0,"msg":"success","data":{"user_id":"...","token":"..."}}`
|
|
58
|
+
|
|
59
|
+
A ready-to-use helper (standard library only, no hard-coded credentials) is
|
|
60
|
+
[`examples/register_bot.py`](examples/register_bot.py):
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
export IMBOT_API_URL="https://api.juggleim.com/apigateway"
|
|
64
|
+
export IMBOT_APPKEY="<your-appkey>"
|
|
65
|
+
export IMBOT_APPSECRET="<your-appsecret>"
|
|
66
|
+
|
|
67
|
+
# register a bot and print its token
|
|
68
|
+
python examples/register_bot.py --bot-id my-bot --nickname "My Bot"
|
|
69
|
+
|
|
70
|
+
# or register a normal user
|
|
71
|
+
python examples/register_bot.py --user --user-id u1 --nickname "User 1"
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
> Keep your AppSecret on the server side — never ship it inside client apps.
|
|
75
|
+
> If the Server API host presents an expired/invalid TLS certificate, pass
|
|
76
|
+
> `--insecure` to bypass verification (use only against endpoints you trust).
|
|
77
|
+
|
|
47
78
|
## Feature overview
|
|
48
79
|
|
|
49
80
|
- Connection management: `connect`, `disconnect`, `logout`, heartbeat keep-alive,
|
|
@@ -37,6 +37,35 @@ pip install .
|
|
|
37
37
|
|
|
38
38
|
> Token 由你的 JuggleIM 应用服务端 / 控制台用 AppKey + AppSecret 通过 Server API 颁发。SDK 本身只负责建立长连接与收发消息。
|
|
39
39
|
|
|
40
|
+
## 获取 Token
|
|
41
|
+
|
|
42
|
+
`connect(token)` 需要一个用户级 Token,由应用服务端通过 JuggleIM Server API 用
|
|
43
|
+
AppKey + AppSecret 颁发。注册一个 bot(或用户)即可拿到 Token:
|
|
44
|
+
|
|
45
|
+
- 接口:`POST {ServerAPI}/bots/register`(或 `/users/register`)
|
|
46
|
+
- 鉴权头:`appkey`、`nonce`(0-9999 随机)、`timestamp`(毫秒)、
|
|
47
|
+
`signature = lowercase_hex( SHA1(AppSecret + nonce + timestamp) )`、
|
|
48
|
+
`Content-Type: application/json`
|
|
49
|
+
- 返回:`{"code":0,"msg":"success","data":{"user_id":"...","token":"..."}}`
|
|
50
|
+
|
|
51
|
+
提供了开箱即用的脚本(纯标准库、不硬编码凭证)
|
|
52
|
+
[`examples/register_bot.py`](examples/register_bot.py):
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
export IMBOT_API_URL="https://api.juggleim.com/apigateway"
|
|
56
|
+
export IMBOT_APPKEY="<你的 appkey>"
|
|
57
|
+
export IMBOT_APPSECRET="<你的 appsecret>"
|
|
58
|
+
|
|
59
|
+
# 注册一个 bot 并打印其 token
|
|
60
|
+
python examples/register_bot.py --bot-id my-bot --nickname "My Bot"
|
|
61
|
+
|
|
62
|
+
# 或注册一个普通用户
|
|
63
|
+
python examples/register_bot.py --user --user-id u1 --nickname "User 1"
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
> AppSecret 只应保存在服务端,切勿打包进客户端应用。
|
|
67
|
+
> 若 Server API 域名的 TLS 证书已过期 / 无效,可加 `--insecure` 跳过校验(仅对你信任的端点使用)。
|
|
68
|
+
|
|
40
69
|
## 能力概览
|
|
41
70
|
|
|
42
71
|
- 连接管理:`connect`、`disconnect`、`logout`、心跳保活、断线自动重连
|
|
@@ -5,6 +5,27 @@
|
|
|
5
5
|
The wire protocol implemented by this SDK interoperates with the other JuggleIM
|
|
6
6
|
client SDKs and the JuggleIM server.
|
|
7
7
|
|
|
8
|
+
## Server API: obtaining a token
|
|
9
|
+
|
|
10
|
+
`connect(token)` needs a user token, minted via the JuggleIM **Server API**
|
|
11
|
+
(HTTP) using your AppKey + AppSecret. This is separate from the WebSocket wire
|
|
12
|
+
protocol below.
|
|
13
|
+
|
|
14
|
+
- Register a bot: `POST {ServerAPI}/bots/register` with JSON body
|
|
15
|
+
`{"bot_id": "...", "nickname": "...", "ext_fields": {}}`.
|
|
16
|
+
- Register a user: `POST {ServerAPI}/users/register` with `{"user_id": "...", ...}`.
|
|
17
|
+
- Auth headers on every Server API request:
|
|
18
|
+
- `appkey`: your AppKey
|
|
19
|
+
- `nonce`: random integer `0..9999` as a string
|
|
20
|
+
- `timestamp`: current epoch milliseconds as a string
|
|
21
|
+
- `signature`: `lowercase_hex( SHA1(AppSecret + nonce + timestamp) )`
|
|
22
|
+
- `Content-Type: application/json`
|
|
23
|
+
- Response envelope: `{"code":0,"msg":"success","data":{"user_id":"...","token":"..."}}`.
|
|
24
|
+
Use `data.token` as the argument to `connect`.
|
|
25
|
+
|
|
26
|
+
See [`examples/register_bot.py`](../examples/register_bot.py) for a runnable
|
|
27
|
+
reference (standard library only, credentials read from env/flags).
|
|
28
|
+
|
|
8
29
|
## Connection
|
|
9
30
|
|
|
10
31
|
- Address: the `address` passed to `ImBotClient(address, app_key)` is the base
|
|
@@ -4,6 +4,25 @@
|
|
|
4
4
|
|
|
5
5
|
本 SDK 实现的线协议可与其它 JuggleIM 客户端 SDK 及 JuggleIM 服务端互通。
|
|
6
6
|
|
|
7
|
+
## Server API:获取 Token
|
|
8
|
+
|
|
9
|
+
`connect(token)` 需要一个用户 Token,通过 JuggleIM **Server API**(HTTP)用
|
|
10
|
+
AppKey + AppSecret 颁发。这与下文的 WebSocket 线协议是相互独立的。
|
|
11
|
+
|
|
12
|
+
- 注册 bot:`POST {ServerAPI}/bots/register`,JSON body
|
|
13
|
+
`{"bot_id": "...", "nickname": "...", "ext_fields": {}}`。
|
|
14
|
+
- 注册用户:`POST {ServerAPI}/users/register`,body 为 `{"user_id": "...", ...}`。
|
|
15
|
+
- 每个 Server API 请求的鉴权头:
|
|
16
|
+
- `appkey`:你的 AppKey
|
|
17
|
+
- `nonce`:`0..9999` 的随机整数(字符串)
|
|
18
|
+
- `timestamp`:当前毫秒时间戳(字符串)
|
|
19
|
+
- `signature`:`lowercase_hex( SHA1(AppSecret + nonce + timestamp) )`
|
|
20
|
+
- `Content-Type: application/json`
|
|
21
|
+
- 返回信封:`{"code":0,"msg":"success","data":{"user_id":"...","token":"..."}}`,
|
|
22
|
+
其中 `data.token` 即用于 `connect` 的 Token。
|
|
23
|
+
|
|
24
|
+
可运行的参考见 [`examples/register_bot.py`](../examples/register_bot.py)(纯标准库,凭证从环境变量/参数读取)。
|
|
25
|
+
|
|
7
26
|
## 连接
|
|
8
27
|
|
|
9
28
|
- 地址:`ImBotClient(address, app_key)` 中的 `address` 为基础地址(`ws://host`
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
"""Register a bot (or user) via the JuggleIM Server API and print its token.
|
|
2
|
+
|
|
3
|
+
The token returned here is what `ImBotClient.connect(token)` expects.
|
|
4
|
+
|
|
5
|
+
Authentication (JuggleIM Server API): each request carries the headers
|
|
6
|
+
``appkey``, ``nonce`` (random 0-9999), ``timestamp`` (epoch ms) and
|
|
7
|
+
``signature = lowercase_hex( SHA1(AppSecret + nonce + timestamp) )``.
|
|
8
|
+
|
|
9
|
+
No server credentials are hard-coded — supply them via environment variables or
|
|
10
|
+
CLI flags:
|
|
11
|
+
|
|
12
|
+
export IMBOT_API_URL="https://api.juggleim.com/apigateway"
|
|
13
|
+
export IMBOT_APPKEY="<your-appkey>"
|
|
14
|
+
export IMBOT_APPSECRET="<your-appsecret>"
|
|
15
|
+
|
|
16
|
+
# register a bot
|
|
17
|
+
python examples/register_bot.py --bot-id my-bot --nickname "My Bot"
|
|
18
|
+
|
|
19
|
+
# or register a normal user
|
|
20
|
+
python examples/register_bot.py --user --user-id u1 --nickname "User 1"
|
|
21
|
+
|
|
22
|
+
Uses only the Python standard library.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
import argparse
|
|
26
|
+
import hashlib
|
|
27
|
+
import json
|
|
28
|
+
import os
|
|
29
|
+
import random
|
|
30
|
+
import ssl
|
|
31
|
+
import sys
|
|
32
|
+
import time
|
|
33
|
+
import urllib.request
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def _auth_headers(appsecret: str, appkey: str) -> dict:
|
|
37
|
+
nonce = str(random.randint(0, 9999))
|
|
38
|
+
timestamp = str(int(time.time() * 1000))
|
|
39
|
+
signature = hashlib.sha1((appsecret + nonce + timestamp).encode("utf-8")).hexdigest()
|
|
40
|
+
return {
|
|
41
|
+
"Content-Type": "application/json",
|
|
42
|
+
"appkey": appkey,
|
|
43
|
+
"nonce": nonce,
|
|
44
|
+
"timestamp": timestamp,
|
|
45
|
+
"signature": signature,
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def _post(api_url: str, path: str, appkey: str, appsecret: str, body: dict, insecure: bool):
|
|
50
|
+
url = api_url.rstrip("/") + path
|
|
51
|
+
data = json.dumps(body).encode("utf-8")
|
|
52
|
+
req = urllib.request.Request(
|
|
53
|
+
url, data=data, headers=_auth_headers(appsecret, appkey), method="POST"
|
|
54
|
+
)
|
|
55
|
+
ctx = ssl._create_unverified_context() if insecure else None
|
|
56
|
+
with urllib.request.urlopen(req, timeout=15, context=ctx) as resp:
|
|
57
|
+
return resp.status, resp.read().decode("utf-8")
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def main() -> int:
|
|
61
|
+
parser = argparse.ArgumentParser(description="Register a JuggleIM bot/user and print its token")
|
|
62
|
+
parser.add_argument("--api-url", default=os.getenv("IMBOT_API_URL", ""),
|
|
63
|
+
help="Server API base, e.g. https://api.juggleim.com/apigateway (env IMBOT_API_URL)")
|
|
64
|
+
parser.add_argument("--appkey", default=os.getenv("IMBOT_APPKEY", ""),
|
|
65
|
+
help="App AppKey (env IMBOT_APPKEY)")
|
|
66
|
+
parser.add_argument("--appsecret", default=os.getenv("IMBOT_APPSECRET", ""),
|
|
67
|
+
help="App AppSecret (env IMBOT_APPSECRET)")
|
|
68
|
+
parser.add_argument("--bot-id", default="", help="bot id to register")
|
|
69
|
+
parser.add_argument("--user-id", default="", help="user id to register (with --user)")
|
|
70
|
+
parser.add_argument("--nickname", default="", help="display name")
|
|
71
|
+
parser.add_argument("--user", action="store_true",
|
|
72
|
+
help="register a normal user (/users/register) instead of a bot")
|
|
73
|
+
parser.add_argument("--insecure", action="store_true",
|
|
74
|
+
help="skip TLS verification (workaround for an expired server certificate)")
|
|
75
|
+
args = parser.parse_args()
|
|
76
|
+
|
|
77
|
+
missing = [n for n, v in (("--api-url", args.api_url), ("--appkey", args.appkey),
|
|
78
|
+
("--appsecret", args.appsecret)) if not v]
|
|
79
|
+
if missing:
|
|
80
|
+
print("error: missing required config: " + ", ".join(missing)
|
|
81
|
+
+ " (pass the flag or set the matching IMBOT_* env var)", file=sys.stderr)
|
|
82
|
+
return 2
|
|
83
|
+
|
|
84
|
+
if args.user:
|
|
85
|
+
ident = args.user_id
|
|
86
|
+
if not ident:
|
|
87
|
+
print("error: --user-id is required with --user", file=sys.stderr)
|
|
88
|
+
return 2
|
|
89
|
+
path = "/users/register"
|
|
90
|
+
body = {"user_id": ident, "nickname": args.nickname, "ext_fields": {}}
|
|
91
|
+
else:
|
|
92
|
+
ident = args.bot_id
|
|
93
|
+
if not ident:
|
|
94
|
+
print("error: --bot-id is required", file=sys.stderr)
|
|
95
|
+
return 2
|
|
96
|
+
path = "/bots/register"
|
|
97
|
+
body = {"bot_id": ident, "nickname": args.nickname, "ext_fields": {}}
|
|
98
|
+
|
|
99
|
+
try:
|
|
100
|
+
status, text = _post(args.api_url, path, args.appkey, args.appsecret, body, args.insecure)
|
|
101
|
+
except Exception as exc: # noqa: BLE001
|
|
102
|
+
print(f"request failed: {exc}", file=sys.stderr)
|
|
103
|
+
if "CERTIFICATE_VERIFY_FAILED" in str(exc):
|
|
104
|
+
print("hint: the server's TLS certificate may be invalid/expired; "
|
|
105
|
+
"retry with --insecure if you trust the endpoint.", file=sys.stderr)
|
|
106
|
+
return 1
|
|
107
|
+
|
|
108
|
+
try:
|
|
109
|
+
payload = json.loads(text)
|
|
110
|
+
except ValueError:
|
|
111
|
+
print(f"HTTP {status}, non-JSON response: {text}", file=sys.stderr)
|
|
112
|
+
return 1
|
|
113
|
+
|
|
114
|
+
if payload.get("code") != 0:
|
|
115
|
+
print(f"register failed: HTTP {status} {text}", file=sys.stderr)
|
|
116
|
+
return 1
|
|
117
|
+
|
|
118
|
+
data = payload.get("data", {})
|
|
119
|
+
print(f"user_id: {data.get('user_id', '')}")
|
|
120
|
+
print(f"token: {data.get('token', '')}")
|
|
121
|
+
return 0
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
if __name__ == "__main__":
|
|
125
|
+
raise SystemExit(main())
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: imbot-sdk-python
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.2
|
|
4
4
|
Summary: JuggleIM Python Bot SDK — WebSocket long-connection IM client for bots and server-side agents
|
|
5
5
|
Author-email: Tyler <tyler@juggle.im>
|
|
6
6
|
Maintainer-email: Tyler <tyler@juggle.im>
|
|
@@ -78,6 +78,37 @@ pip install .
|
|
|
78
78
|
> + AppSecret via the Server API. The SDK itself only establishes the
|
|
79
79
|
> connection and sends/receives messages.
|
|
80
80
|
|
|
81
|
+
## Obtaining a token
|
|
82
|
+
|
|
83
|
+
`connect(token)` needs a per-user token. Tokens are minted by your app server
|
|
84
|
+
through the JuggleIM Server API using your AppKey + AppSecret. Registering a bot
|
|
85
|
+
(or a user) returns a token:
|
|
86
|
+
|
|
87
|
+
- Endpoint: `POST {ServerAPI}/bots/register` (or `/users/register`)
|
|
88
|
+
- Auth headers: `appkey`, `nonce` (random 0-9999), `timestamp` (epoch ms),
|
|
89
|
+
`signature = lowercase_hex( SHA1(AppSecret + nonce + timestamp) )`,
|
|
90
|
+
`Content-Type: application/json`
|
|
91
|
+
- Response: `{"code":0,"msg":"success","data":{"user_id":"...","token":"..."}}`
|
|
92
|
+
|
|
93
|
+
A ready-to-use helper (standard library only, no hard-coded credentials) is
|
|
94
|
+
[`examples/register_bot.py`](examples/register_bot.py):
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
export IMBOT_API_URL="https://api.juggleim.com/apigateway"
|
|
98
|
+
export IMBOT_APPKEY="<your-appkey>"
|
|
99
|
+
export IMBOT_APPSECRET="<your-appsecret>"
|
|
100
|
+
|
|
101
|
+
# register a bot and print its token
|
|
102
|
+
python examples/register_bot.py --bot-id my-bot --nickname "My Bot"
|
|
103
|
+
|
|
104
|
+
# or register a normal user
|
|
105
|
+
python examples/register_bot.py --user --user-id u1 --nickname "User 1"
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
> Keep your AppSecret on the server side — never ship it inside client apps.
|
|
109
|
+
> If the Server API host presents an expired/invalid TLS certificate, pass
|
|
110
|
+
> `--insecure` to bypass verification (use only against endpoints you trust).
|
|
111
|
+
|
|
81
112
|
## Feature overview
|
|
82
113
|
|
|
83
114
|
- Connection management: `connect`, `disconnect`, `logout`, heartbeat keep-alive,
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "imbot-sdk-python"
|
|
7
|
-
version = "0.1.
|
|
7
|
+
version = "0.1.2"
|
|
8
8
|
description = "JuggleIM Python Bot SDK — WebSocket long-connection IM client for bots and server-side agents"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.8"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{imbot_sdk_python-0.1.1 → imbot_sdk_python-0.1.2}/imbot_sdk_python.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|