Skip to main content

openim_sdk

Python SDK and CLI for OpenIM-style login, send message, and receive message.

Install locally

python3 -m pip install . --force-reinstall --no-deps

Modes

  • OpenIMWSSDK (recommended): websocket direct connection (gob + gzip + protobuf) with heartbeat and auto reconnect.
  • OpenIMSDK: HTTP polling fallback.
  • openim-cli: account bootstrap, auth status, and outbound notification commands built on top of OpenIMWSSDK.

CLI quick start

Install this repository, then run:

openim-cli --help
openim-cli config init --token "$OPENIM_TOKEN" --ws-addr ws://127.0.0.1:10001/msg_gateway --default true
openim-cli auth status --format pretty
openim-cli notify +send --to user:u2 --text "hello"
openim-cli notify +send --to group:g1 --text '<at user_id="u2">Gimmus</at> 你好'

Supported commands:

  • config init|list|use|remove
  • auth status
  • notify +send

WebSocket quick start

from openim_sdk import OpenIMWSSDK, WSConfig

sdk = OpenIMWSSDK(
    WSConfig(ws_addr="ws://127.0.0.1:10001/msg_gateway", data_dir="./openim_py_data")
)
sdk.login(user_id="u1", token="YOUR_TOKEN")
sdk.start()
sdk.send_text("hello", recv_id="u2")

See openim_sdk/example_ws.py for a runnable demo script.

WebSocket detailed usage

1. Build config

WSConfig parameters:

  • ws_addr (required): websocket gateway address, e.g. ws://127.0.0.1:10001/msg_gateway
  • api_addr: HTTP API address for profile fetch (used to cache self info for send), e.g. http://127.0.0.1:10002; when empty, sdk falls back to env OPENIM_API_ADDR
  • data_dir: local sqlite directory, default ./data
  • platform_id: platform ID sent to server, default 1
  • timeout_seconds: request/response wait timeout, default 1000
  • pull_batch_size: sync page size, default 100
  • sdk_version: value sent in ws query, default python-ws-0.1.0
  • auto_sync_on_connect: run sync_once() immediately after first connect, default False
  • auto_sync_on_reconnect: auto sync after reconnect, default True
  • auto_reconnect: reconnect automatically on disconnect, default True
  • max_reconnect_attempts: reconnect attempt cap, default 300
  • reconnect_backoff_seconds: reconnect interval sequence, default (1, 2, 4, 8, 16)
  • enable_heartbeat: send ws ping periodically, default True
  • heartbeat_interval_seconds: ping interval, default 24
  • heartbeat_pong_timeout_seconds: pong timeout, default 30
  • self_user_info_cache_ttl_seconds: in-memory cache ttl for self profile (senderNickname/senderFaceURL), default 600 seconds

2. Register callbacks

Available callbacks in OpenIMWSSDK(...):

  • on_recv_new_message(msg: WSMessage): called for online real-time messages
  • on_recv_offline_new_message(msg: WSMessage): called for offline/sync messages
  • on_connecting(): called before connect/reconnect attempts
  • on_connect_success(): called after successful connect/reconnect
  • on_connect_failed(exc): called when one connect attempt fails
  • on_kicked_offline(): called when server returns kick event
  • on_error(exc): called on internal errors (decode/send/read/reconnect, etc.)
  • logger(text): sdk log output callback

2.1 WSMessage fields

Raw payload keys:

  • conversationID: conversation id (sdk adds this key)
  • sendID, recvID, groupID
  • clientMsgID, serverMsgID
  • senderPlatformID, senderNickname, senderFaceURL
  • sessionType (1 single, 2 group, 3 super group)
  • msgFrom, contentType, content
  • seq, sendTime, createTime
  • status, isRead
  • options (dict[str, bool])
  • offlinePushInfo (dict)
  • atUserIDList (list[str])
  • attachedInfo, ex

Python field names in WSMessage:

  • conversation_id, send_id, recv_id, group_id
  • client_msg_id, server_msg_id
  • sender_platform_id, sender_nickname, sender_face_url
  • session_type, msg_from, content_type, content
  • seq, send_time, create_time, status, is_read
  • options, offline_push_info, at_user_id_list, attached_info, ex
  • raw: original dictionary payload
  • content_json: parsed JSON from content (or None when not valid JSON)
  • content_obj: typed content object parsed by content_type

content_type -> content_obj mapping (same as sdk_struct.go):

  • 101 -> TextElem
  • 102 -> PictureElem
  • 103 -> SoundElem
  • 104 -> VideoElem
  • 105 -> FileElem
  • 106 -> AtTextElem
  • 107 -> MergeElem
  • 108 -> CardElem
  • 109 -> LocationElem
  • 110/119/120 -> CustomElem
  • 113 -> TypingElem
  • 114 -> QuoteElem
  • 115 -> FaceElem
  • 117 -> AdvancedTextElem
  • 118 -> MarkdownTextElem
  • other content types -> NotificationElem

Minimal callback example:

from openim_sdk import OpenIMWSSDK, WSConfig, WSMessage, TextElem, PictureElem


def on_new_model(msg: WSMessage) -> None:
    if isinstance(msg.content_obj, TextElem):
        print("[text]", msg.content_obj.content)
    elif isinstance(msg.content_obj, PictureElem):
        print("[picture]", msg.content_obj.source_picture)
    else:
        print("[other]", msg.content_type, msg.content_obj)


sdk = OpenIMWSSDK(
    WSConfig(ws_addr="ws://127.0.0.1:10001/msg_gateway"),
    on_recv_new_message=on_new_model,
)
import time

from openim_sdk import OpenIMWSSDK, TextElem, WSConfig, WSSDKError, WSMessage


def on_new(msg: WSMessage) -> None:
    if isinstance(msg.content_obj, TextElem):
        print("[new text]", msg.send_id, "->", msg.recv_id, msg.content_obj.content)
    else:
        print("[new]", msg.send_id, "->", msg.recv_id, msg.content_type, msg.content_obj)


def on_offline(msg: WSMessage) -> None:
    print("[offline]", msg.client_msg_id, msg.seq)


def on_err(exc: Exception) -> None:
    print("[error]", exc)


sdk = OpenIMWSSDK(
    WSConfig(
        ws_addr="ws://127.0.0.1:10001/msg_gateway",
        api_addr="http://127.0.0.1:10002",
        data_dir="./openim_py_data",
        auto_sync_on_connect=True,
        auto_sync_on_reconnect=True,
    ),
    on_recv_new_message=on_new,
    on_recv_offline_new_message=on_offline,
    on_connecting=lambda: print("[ws] connecting"),
    on_connect_success=lambda: print("[ws] connected"),
    on_connect_failed=lambda e: print("[ws] connect failed:", e),
    on_kicked_offline=lambda: print("[ws] kicked offline"),
    on_error=on_err,
    logger=lambda s: print("[sdk]", s),
)

try:
    # 1) login first
    sdk.login(user_id="u1", token="YOUR_TOKEN")
    # 2) then start websocket threads
    sdk.start()

    # send peer message
    ack = sdk.send_text("hello from ws sdk", recv_id="u2")
    print("send ack:", ack)  # {"serverMsgID": "...", "clientMsgID": "...", "sendTime": ...}

    # keep process alive
    while True:
        time.sleep(1)
except WSSDKError as e:
    print("business error:", e.err_code, e.err_msg)
except KeyboardInterrupt:
    pass
finally:
    # stop background threads and close db
    sdk.logout()

4. Sending messages

  • Single chat:
sdk.send_text("hello", recv_id="u2")
sdk.send_at_text("@Gimmus 你好", at_user_list=["u2"], at_users_info=[{"atUserID": "u2", "groupNickname": "Gimmus"}], group_id="g1")
  • Group chat:
sdk.send_text("hello group", group_id="g123", session_type=2)

send_text(...) notes:

  • must pass one of recv_id or group_id
  • session_type defaults to single chat (1) if recv_id is set, otherwise group (2)
  • if WSConfig.api_addr is set, sdk fetches self profile (/user/get_users_info) and caches it in memory (ttl controlled by self_user_info_cache_ttl_seconds, default 10 minutes), then auto-fills senderNickname and senderFaceURL on send
  • supported session values:
    • 1: single chat
    • 2: group chat
    • 3: super group chat

Media/file messages:

sdk.send_image("/absolute/path/demo.png", recv_id="u2")
sdk.send_sound("/absolute/path/demo.mp3", duration=9, recv_id="u2")
sdk.send_video(
    "/absolute/path/demo.mp4",
    duration=15000,
    snapshot_path="/absolute/path/demo-cover.jpg",
    recv_id="u2",
)
sdk.send_file("/absolute/path/report.pdf", recv_id="u2")

URL-based variants:

sdk.send_image_by_url(source_url="https://cdn.example.com/demo.png", width=1280, height=720, recv_id="u2")
sdk.send_video_by_url(video_url="https://cdn.example.com/demo.mp4", duration=15000, recv_id="u2")
sdk.send_file_by_url(source_url="https://cdn.example.com/report.pdf", file_name="report.pdf", recv_id="u2")

Media upload notes:

  • local media/file sending uses OpenIM object upload APIs before message send
  • SDKConfig.api_addr / WSConfig.api_addr must be configured for local media/file sending
  • send_video(...) requires duration in milliseconds; when snapshot_path is omitted, the SDK will try to extract the first video frame as the cover image with local ffmpeg
  • send_sound(...) requires duration
  • CLI notify +send --video ... now probes local video duration in milliseconds with ffprobe and sends a real video message instead of falling back to file sending
  • CLI notify +send --text ... supports mention markup like <at user_id="u2">Gimmus</at> 你好, which is sent as OpenIM AT_TEXT (106)
  • send_picture is an alias of send_image

5. Manual sync

If you want explicit control (instead of auto_sync_on_connect/reconnect), call:

sdk.sync_once()

This pulls missing seq ranges and dispatches them through on_recv_offline_new_message.

6. Lifecycle and best practices

  • call order should be: login(...) -> start() -> send/recv -> logout()
  • stop() only stops ws threads; logout() stops threads and closes local storage
  • keep your process alive after start(), otherwise daemon threads exit with process
  • for production:
    • keep auto_reconnect=True
    • keep heartbeat enabled
    • handle on_error and on_connect_failed for observability/retry alerts
    • persist your own app-level offsets/state if required

HTTP polling quick start

from openim_sdk import OpenIMSDK, SDKConfig

sdk = OpenIMSDK(
    SDKConfig(api_addr="http://127.0.0.1:10002", data_dir="./openim_py_data")
)
sdk.login(user_id="u1", token="YOUR_TOKEN")
sdk.start_receiving()
sdk.send_text("hello", recv_id="u2")
me = sdk.get_self_user_info()
print(me.user_id, me.nickname, me.face_url)

WebSocket features

  • Login with user_id + token
  • Send text message with protobuf payload (MsgData)
  • Receive PushMessages from ws binary frames
  • Gob encode/decode for GeneralWsReq/GeneralWsResp
  • Gzip frame compression/decompression
  • Heartbeat (ping/pong)
  • Auto reconnect with backoff (1,2,4,8,16 seconds loop by default)
  • Auto sync missed messages on connect/reconnect
  • Local SQLite persistence:
    • message rows
    • per-conversation latest synced seq

Local database

  • WS mode: <data_dir>/OpenIM_pyws_<user_id>.db
  • HTTP mode: <data_dir>/OpenIM_py_<user_id>.db

Tables:

  • conversation_seq(conversation_id, last_seq)
  • messages(...)

Metadata

Release files for openim-sdk-core 0.1.11

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for openim-sdk-core 0.1.11
File Size Uploaded
openim_sdk_core-0.1.11.tar.gz 75.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for openim-sdk-core 0.1.11
File Interpreter ABI Platform
openim_sdk_core-0.1.11-py3-none-any.whl Python 3 none any Details

Total release size: 149.7 kB

Release files / openim_sdk_core-0.1.11.tar.gz

Download URL openim_sdk_core-0.1.11.tar.gz
Size 75.0 kB
Tags Source
SHA-256 checksum
How to use checksums
7c57f96963780a080069b4177406edac23f9f0bc34ab10fcea208dfe07a8bb4d
BLAKE2b-256 checksum
How to use checksums
0f7addd85eef439e826cafe59a593c41d050d626136f91d5091c9c37069fa9c9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.13

Release files / openim_sdk_core-0.1.11-py3-none-any.whl

Download URL openim_sdk_core-0.1.11-py3-none-any.whl
Size 74.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
4ae1dcdd6096b79e6e117186c82eb2e7d3efcc539e373d1acd52b0c979de62d9
BLAKE2b-256 checksum
How to use checksums
f67d053b8a5cb206ffaba9a6423b75ebaaf7cc79a5a4073b5b1651eb509aefb4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.13

Release history Release notifications | RSS feed

This release

0.1.11 This release

2 release files

0.1.10

2 release files

0.1.9

2 release files

0.1.8

2 release files

0.1.7

2 release files

0.1.6

2 release files

0.1.5

2 release files

0.1.4

2 release files

0.1.3

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page