bridgeclient

package
v0.34.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 22, 2026 License: MIT Imports: 12 Imported by: 0

README

BridgeClient SDK

Go SDK for connecting external platform adapters to HotPlex via the BridgeServer WebSocket gateway.

What is this?

HotPlex's BridgeServer (internal/server/bridge.go) is a WebSocket gateway that allows external platform adapters (DingTalk, WeChat, Feishu, etc.) to connect to HotPlex without being compiled into the same binary. BridgeClient is the SDK that adapter developers use to connect.

External Adapter (your DingTalk bot) ──BridgeClient──WebSocket──> BridgeServer
                                                                          │
                                                                          ▼
                                                                  HotPlex Engine

Quick Start

package main

import (
    "context"
    "log"
    "os"

    "github.com/hrygo/hotplex/cmd/bridge-client"
)

func main() {
    client, err := bridgeclient.New(
        bridgeclient.URL("wss://hotplex.internal/bridge"),
        bridgeclient.Platform("dingtalk"),
        bridgeclient.AuthToken(os.Getenv("HOTPLEX_BRIDGE_TOKEN")),
        bridgeclient.Capabilities(
            bridgeclient.CapText,
            bridgeclient.CapCard,
            bridgeclient.CapButtons,
            bridgeclient.CapTyping,
        ),
    )
    if err != nil {
        log.Fatal(err)
    }

    client.OnMessage(func(msg *bridgeclient.Message) *bridgeclient.Reply {
        log.Printf("session=%s user=%s: %s",
            msg.SessionKey, msg.Metadata.UserID, msg.Content)

        return &bridgeclient.Reply{
            Content:    "Hello from your DingTalk bot!",
            SessionKey: msg.SessionKey,
        }
    })

    ctx := context.Background()
    if err := client.Connect(ctx); err != nil {
        log.Fatal(err)
    }
    defer client.Close()

    <-ctx.Done()
}

Configuration

Option Required Description
URL Yes BridgeServer WebSocket URL (e.g., ws://localhost:8080/bridge)
Platform Yes Platform identifier (e.g., dingtalk, wechat, lark)
AuthToken Yes Token matching bridge_token in HotPlex config
Capabilities No Defaults to [CapText] if not set

Capabilities

Declare what your adapter supports when connecting:

Constant Description
CapText Plain text messages
CapImage Image uploads
CapCard Rich card messages
CapButtons Interactive buttons
CapTyping Typing indicators
CapEdit Edit sent messages
CapDelete Delete sent messages
CapReact Emoji reactions
CapThread Thread/reply support

Message Flow

Inbound (HotPlex → Your Adapter)

HotPlex sends user messages to your adapter via the OnMessage handler:

client.OnMessage(func(msg *bridgeclient.Message) *bridgeclient.Reply {
    // msg.SessionKey  — Session identifier (pass back in Reply)
    // msg.Content     — Message text
    // msg.Metadata.UserID   — User identity
    // msg.Metadata.RoomID   — Room/channel identity
    // msg.Metadata.ThreadID — Thread/thread_ts identity
    // msg.Metadata.Platform — Always "hotplex"

    reply := yourAI.Process(msg.Content)
    return &bridgeclient.Reply{
        Content:    reply.Text,
        SessionKey: msg.SessionKey,
    }
})
Events (HotPlex → Your Adapter)

HotPlex can also send events (e.g., typing, stream_start, stream_end):

client.OnEvent(func(evt *bridgeclient.Event) {
    switch evt.Event {
    case "typing":
        // Show typing indicator in DingTalk UI
    case "stream_end":
        // Final message chunk received
    }
})
Outbound (Your Adapter → HotPlex)

If HotPlex needs to receive messages initiated by your adapter (e.g., a DingTalk outbound webhook triggered by an external event):

err := client.SendMessage(ctx, &bridgeclient.Message{
    SessionKey: "session-from-dingtalk",
    Content:    "Outbound DingTalk message received",
    Metadata: bridgeclient.Metadata{
        UserID: "openid-xxx",
        RoomID: "chatid-yyy",
    },
})

Running the Example

# 1. Start HotPlex with bridge enabled
# In your config.yaml or .env:
#   bridge_port=8080
#   bridge_token=secret

# 2. Run the example DingTalk adapter
cd cmd/bridge-client/example
go run main.go

Bridge Wire Protocol

The SDK implements the Bridge Wire Protocol — a JSON envelope over WebSocket:

Direction Type Description
Client → Server register Handshake: platform name + capabilities
Server → Client message Inbound message from HotPlex engine
Client → Server reply Response to a message
Server → Client event Engine events (typing, stream, etc.)
Either error Protocol errors

See internal/server/bridge.go for the full protocol specification.

HotPlex Configuration

Enable BridgeServer in your config.yaml:

server:
  bridge_port: "8080"    # Separate HTTP server for bridge adapters
  bridge_token: "secret" # Token adapters must present

Or via environment variables:

HOTPLEX_BRIDGE_PORT=8080
HOTPLEX_BRIDGE_TOKEN=secret

Documentation

Overview

Package bridgeclient provides a Go SDK for connecting external platform adapters to HotPlex via the BridgeServer WebSocket gateway.

Usage:

client := bridgeclient.New(
	bridgeclient.URL("wss://hotplex.internal:8080/bridge"),
	bridgeclient.Platform("dingtalk"),
	bridgeclient.Capabilities(bridgeclient.CapText, bridgeclient.CapCard),
	bridgeclient.AuthToken(os.Getenv("HOTPLEX_BRIDGE_TOKEN")),
)

client.OnMessage(func(msg *bridgeclient.Message) *bridgeclient.Reply {
	// Process msg.Content, msg.SessionKey, msg.Metadata
	return &bridgeclient.Reply{
		Content:    "Hello from DingTalk!",
		SessionKey: msg.SessionKey,
	}
})

ctx := context.Background()
if err := client.Connect(ctx); err != nil {
	log.Fatal(err)
}
defer client.Close()

// Block until disconnected
<-ctx.Done()

Index

Constants

View Source
const (
	CapText    = bridgewire.CapText
	CapImage   = bridgewire.CapImage
	CapCard    = bridgewire.CapCard
	CapButtons = bridgewire.CapButtons
	CapTyping  = bridgewire.CapTyping
	CapEdit    = bridgewire.CapEdit
	CapDelete  = bridgewire.CapDelete
	CapReact   = bridgewire.CapReact
	CapThread  = bridgewire.CapThread
)

Cap* aliases for the public API (mirrors bridgewire constants).

Variables

This section is empty.

Functions

This section is empty.

Types

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client is a BridgeClient that connects to HotPlex BridgeServer as a WebSocket client.

func New

func New(opts ...Option) (*Client, error)

New creates a new BridgeClient with the given options.

func (*Client) Close

func (c *Client) Close() error

Close gracefully shuts down the client connection.

func (*Client) Connect

func (c *Client) Connect(ctx context.Context) error

Connect establishes a WebSocket connection to BridgeServer, performs the register handshake, and starts background goroutines to handle incoming messages and events. It blocks until the context is cancelled or a fatal error occurs.

func (*Client) OnEvent

func (c *Client) OnEvent(h EventHandler)

OnEvent registers a handler for inbound events from HotPlex. Only one handler can be registered; subsequent calls replace the previous one.

func (*Client) OnMessage

func (c *Client) OnMessage(h MessageHandler)

OnMessage registers a handler for inbound messages from HotPlex. Only one handler can be registered; subsequent calls replace the previous one.

func (*Client) SendMessage

func (c *Client) SendMessage(ctx context.Context, msg *Message) error

SendMessage sends a message from the external platform to HotPlex. This is used for inbound messages (e.g., a user sends a DM on DingTalk).

func (*Client) Typing

func (c *Client) Typing(ctx context.Context, sessionKey string) error

Typing sends a typing indicator to HotPlex.

type Error

type Error struct {
	Code    int
	Message string
}

Error represents an error message from HotPlex (server → client).

type Event

type Event struct {
	Event string
	Data  json.RawMessage
	// contains filtered or unexported fields
}

Event represents an inbound event from HotPlex (server → client). Common events: "stream_start", "stream_chunk", "stream_end", "typing_start", "typing_end".

type EventHandler

type EventHandler func(evt *Event)

EventHandler processes inbound events from HotPlex.

type Message

type Message struct {
	SessionKey string
	Content    string
	Metadata   Metadata
	// contains filtered or unexported fields
}

Message represents an inbound message from HotPlex (server → client).

type MessageHandler

type MessageHandler func(msg *Message) *Reply

MessageHandler processes inbound messages from HotPlex and optionally returns a reply.

type Metadata

type Metadata struct {
	UserID   string
	RoomID   string
	ThreadID string
	Platform string
}

Metadata holds message identity fields.

type Option

type Option func(*Client) error

Option configures a BridgeClient.

func AuthToken

func AuthToken(v string) Option

AuthToken sets the token used to authenticate with BridgeServer. This must match the bridge_token configured in HotPlex.

func Capabilities

func Capabilities(caps ...string) Option

Capabilities sets the capabilities this adapter supports. If not set, defaults to CapText.

func HTTPClient

func HTTPClient(hc *http.Client) Option

HTTPClient sets a custom HTTP client for WebSocket dialing. This overrides URL, Timeout, and TLSConfig options.

func Logger

func Logger(l *slog.Logger) Option

Logger sets the logger used by the client. If not set, defaults to slog.Default().

func Platform

func Platform(v string) Option

Platform sets the platform name this adapter represents. This is used as the platform identifier in the Bridge Wire Protocol. Example: "dingtalk", "wechat", "lark"

func ProxyURL

func ProxyURL(raw string) Option

ProxyURL sets a WebSocket proxy URL (ws:// or wss://).

func TLSConfig

func TLSConfig(cfg *tls.Config) Option

TLSConfig sets the TLS configuration for wss:// connections.

func Timeout

func Timeout(d time.Duration) Option

Timeout sets the HTTP client timeout used during connection establishment.

func URL

func URL(v string) Option

URL sets the BridgeServer WebSocket URL. Example: "ws://localhost:8080/bridge" or "wss://hotplex.internal/bridge"

type Reply

type Reply struct {
	Content    string
	SessionKey string
	Metadata   Metadata
}

Reply is returned by a MessageHandler to send a response back to HotPlex.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL