mezonlightsdk

package module
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Jun 21, 2026 License: MIT Imports: 17 Imported by: 0

README

Mezon SDK for Go

A lightweight Go SDK for Mezon chat, ported from the TypeScript package mezon-sdk (in mezonai/mezon-js). It mirrors the mezon-light-sdk-go reference: methods take a context.Context and return errors, optional parameters live in option structs, snowflake IDs are kept as decimal strings, and message-content offsets are UTF-16 code units (JavaScript string indices, so an emoji like 🎉 counts as 2) — matching how the Mezon clients index text.

Features

  • Authenticate as a bot with a bot ID + API key, with an ID token, or restore a session from stored tokens
  • Refresh sessions (single-flight; concurrent callers share one refresh)
  • Create DM / group DM channels
  • Upload attachments
  • Realtime messaging over WebSocket using the protobuf wire protocol (join/leave channels, send/receive messages, heartbeat with automatic dead-connection detection)
  • Rich message content: clickable links (auto-detected or explicit), code/bold markup, user/role/@here mentions, channel hashtags and custom emojis via ContentBuilder — text offsets handled for you
  • Incoming messages arrive with content, mentions and attachments decoded

Installation

go get github.com/quangledang23/mezon-sdk-go

Quick start

package main

import (
	"context"
	"log"

	"github.com/quangledang23/mezon-sdk-go"
)

func main() {
	ctx := context.Background()

	// Authenticate as a bot with credentials from the Mezon developer portal…
	client, err := mezonlightsdk.AuthenticateBot(ctx, mezonlightsdk.AuthenticateBotConfig{
		BotID:  "your-bot-id",
		APIKey: "your-bot-token",
	})
	if err != nil {
		log.Fatal(err)
	}

	// …or with an ID token from an identity provider:
	// client, err := mezonlightsdk.Authenticate(ctx, mezonlightsdk.AuthenticateConfig{
	// 	IDToken:  "id-token-from-provider",
	// 	UserID:   "user-123",
	// 	Username: "johndoe",
	// })

	// …or restore from previously stored tokens:
	// client, err := mezonlightsdk.InitClient(mezonlightsdk.ClientInitConfig{
	// 	Token:        "your-token",
	// 	RefreshToken: "your-refresh-token",
	// 	APIURL:       "https://api.mezon.ai",
	// 	WSURL:        "gw.mezon.ai",
	// 	UserID:       "user-123",
	// })

	// Create a DM channel.
	channel, err := client.CreateDM(ctx, "peer-user-id")
	if err != nil {
		log.Fatal(err)
	}

	// Connect the realtime socket.
	socket := mezonlightsdk.NewLightSocket(client, client.Session())
	err = socket.Connect(ctx, mezonlightsdk.SocketConnectOptions{
		OnError:      func(err error) { log.Println("socket error:", err) },
		OnDisconnect: func() { log.Println("disconnected") },
	})
	if err != nil {
		log.Fatal(err)
	}
	defer socket.Disconnect()

	// Receive messages. The returned function unsubscribes the handler.
	unsubscribe := socket.OnChannelMessage(func(msg *mezonlightsdk.ChannelMessage) {
		log.Printf("received from %s: %v", msg.Username, msg.Content)
	})
	defer unsubscribe()

	// Join the DM channel and send a message.
	if err := socket.JoinDMChannel(ctx, channel.ChannelID); err != nil {
		log.Fatal(err)
	}
	// URLs in plain text become clickable links automatically
	// (set HideLink: true to keep them plain).
	err = socket.SendDM(ctx, mezonlightsdk.SendMessagePayload{
		ChannelID: channel.ChannelID,
		Content:   "Hello! Docs: https://mezon.ai/docs/developer",
	})
	if err != nil {
		log.Fatal(err)
	}

	select {} // keep the process alive to receive messages
}
Sending to a clan channel

LightSocket covers DMs and group DMs. For clan channels, use the underlying DefaultSocket directly:

sock, _ := socket.Socket()

// Channel type 1 = text channel; mode 2 = clan channel message.
_, err = sock.JoinChat(ctx, clanID, channelID, 1, true)
ack, err := sock.WriteChatMessage(ctx, clanID, channelID, 2, true,
	mezonlightsdk.NewTextContent("Hello clan! https://mezon.ai"), nil)

Mezon messages carry plain text (t) plus position-based tokens: mk (markup: links, code, bold), hg (channel hashtags) and ej (custom emojis) inside the content, and a mentions array next to it. All offsets are UTF-16 code units (JavaScript string indices, as the Mezon clients count them — an emoji like 🎉 counts as 2). ContentBuilder assembles them so you never count offsets by hand:

b := mezonlightsdk.NewContentBuilder()
b.Text("Deploy xong ").
	MentionHere().              // "@here", notifies the channel (blue mention)
	Text(", chi tiết: ").
	Link("https://ci.example.com").
	Text(" tại ").
	Hashtag(channelID, "#deploys").
	Text(" — ").
	Bold("quan trọng")

ack, err := sock.WriteChatMessage(ctx, clanID, channelID, 2, true,
	b.Content(), &mezonlightsdk.ChatMessageOptions{
		Mentions:        b.Mentions(),
		MentionEveryone: true, // makes @here actually notify everyone
	})

Also available: MentionUser(userID, "@alice"), MentionRole(roleID, "@admins") (renders green), Code("..."), Emoji(emojiID, ":smile:"), Markup(markupType, text) for the remaining mk types (MarkupTypePre, MarkupTypeTriple, MarkupTypeSingle, MarkupTypeCode, MarkupTypeVoiceLink), and inline images (webhook-style images field, e.g. with a URL from UploadAttachment):

b.Image(&mezonlightsdk.MessageImage{
	Filename: "dog.jpg",
	URL:      "https://cdn.mezon.vn/.../dog.jpg",
	Filetype: "image/jpeg",
	Width:    275,
	Height:   183,
})

Note on @here: clients render a mention as a blue user mention only when its user_id is the sentinel mezonlightsdk.MentionHereUserID ("1775731111020111321", hardcoded in the official clients); a mention without a user ID falls into the role-mention path and renders green. MentionHere() handles this for you.

Receiving messages

Incoming messages arrive decoded: Content is the parsed content JSON, Mentions and Attachments are typed slices (the server sends them as protobuf or JSON; both are handled):

socket.OnChannelMessage(func(msg *mezonlightsdk.ChannelMessage) {
	content, _ := msg.Content.(map[string]any)
	text, _ := content["t"].(string)
	log.Printf("%s: %s (mentions: %d)", msg.Username, text, len(msg.Mentions))
})
Uploading attachments
result, err := client.UploadAttachment(ctx, &mezonlightsdk.ApiUploadAttachmentRequest{
	Filename: "image.png",
	Filetype: "image/png",
	Size:     1024,
	Width:    800,
	Height:   600,
})
// result.URL can be used in message attachments.
Session management
// Refresh before the token expires.
if client.IsSessionExpired() {
	if _, err := client.RefreshSession(ctx); err != nil {
		log.Fatal(err)
	}
}

// Persist the session for later restoration via InitClient.
config := client.ExportSession()

Package layout

Path Contents
. (root) LightClient, LightSocket, DefaultSocket, MezonApi, Session; content.go (outgoing content: ContentBuilder, markup/hashtag/emoji/image tokens, link extraction), message.go (incoming ChannelMessage decoding)
proto Hand-written protobuf wire codecs for the mezon.api and mezon.realtime messages used by the SDK (field numbers mirror the ts-proto generated code in mezon-light-sdk/src/proto)

Differences from the TypeScript SDK

  • Methods take a context.Context and return error instead of promises.
  • WriteChatMessage collects its many optional parameters in ChatMessageOptions.
  • Callbacks (OnChannelMessage, OnDisconnect, …) are struct fields set before Connect.
  • Snowflake IDs remain string in Go structs and are converted to/from int64 varints on the wire, matching ts-proto's int64-as-string behavior (an ID of "0" or "" is omitted from the wire).

Documentation

Overview

Package mezonlightsdk is a lightweight Go SDK for Mezon chat, ported from the TypeScript package mezon-sdk (packages/mezon-sdk in mezonai/mezon-js), following the design of the mezon-light-sdk-go reference: methods take a context.Context and return errors, optional parameters live in option structs, snowflake IDs are kept as decimal strings, and every message-content offset is a UTF-16 code unit (JavaScript string index) so it lines up with how the Mezon clients count them.

Index

Constants

View Source
const (
	// MezonGWURL is the default Mezon Gateway URL.
	MezonGWURL = "https://gw.mezon.ai"

	// MezonWSHost is the default WebSocket host, used when authentication
	// does not return a user-specific one.
	MezonWSHost = "gw.mezon.ai"

	// SocketReadyMaxRetry is the maximum number of retries when waiting for
	// the socket to be ready.
	SocketReadyMaxRetry = 20

	// SocketReadyRetryDelay is the initial delay between socket ready
	// retries (uses exponential backoff).
	SocketReadyRetryDelay = 100 * time.Millisecond

	// ClanDM is the clan ID used for Direct Messages.
	ClanDM = "0"

	// ChannelTypeDM is the channel type for Direct Messages.
	ChannelTypeDM = 3

	// ChannelTypeGroup is the channel type for group DMs.
	ChannelTypeGroup = 2

	// StreamModeDM is the stream mode for Direct Messages.
	StreamModeDM = 4

	// StreamModeGroup is the stream mode for group DMs.
	StreamModeGroup = 3

	// DefaultServerKey is the default server key if none is provided.
	DefaultServerKey = "DefaultServerKey"

	// MentionHereUserID is the sentinel user ID the official clients put in a
	// mention's user_id for "@here" (ID_MENTION_HERE in the Mezon web app).
	// Without it the clients render the mention as a role mention (green)
	// instead of a user mention (blue).
	MentionHereUserID = "1775731111020111321"

	// MentionHereTitle is the literal mention text that must appear in the
	// message content at the mention's s/e offsets.
	MentionHereTitle = "@here"
)
View Source
const (
	// MarkupTypeLink renders the covered text as a clickable link.
	MarkupTypeLink = "lk"
	// MarkupTypePre renders the covered text as a preformatted block.
	MarkupTypePre = "pre"
	// MarkupTypeTriple is a triple-backtick code block.
	MarkupTypeTriple = "t"
	// MarkupTypeSingle is a single-backtick inline code span.
	MarkupTypeSingle = "s"
	// MarkupTypeCode is an inline code span.
	MarkupTypeCode = "c"
	// MarkupTypeBold renders the covered text in bold.
	MarkupTypeBold = "b"
	// MarkupTypeVoiceLink is a link to a voice room.
	MarkupTypeVoiceLink = "vk"
)

Markup types for MessageMarkup.Type (EBacktickType in the Mezon web app).

View Source
const (
	DefaultHeartbeatTimeout = 10 * time.Second
	DefaultSendTimeout      = 10 * time.Second
	DefaultConnectTimeout   = 30 * time.Second
)

Default socket timeouts, mirroring DefaultSocket in socket.gen.ts.

Variables

This section is empty.

Functions

func DecodeAttachments

func DecodeAttachments(data []byte) []*proto.MessageAttachment

DecodeAttachments decodes a channel message attachments payload, which may be either JSON or a protobuf-encoded MessageAttachmentList.

func DecodeMentions

func DecodeMentions(data []byte) []*proto.MessageMention

DecodeMentions decodes a channel message mentions payload, which may be either JSON or a protobuf-encoded MessageMentionList.

func SafeJSONParse

func SafeJSONParse(raw []byte) any

SafeJSONParse decodes raw JSON content. On failure (or for empty input) it returns map[string]any{"t": <raw string>}, mirroring safeJSONParse in the TypeScript SDK.

Types

type APIError

type APIError struct {
	StatusCode int
	Body       string
}

APIError is returned for non-2xx HTTP responses from the Mezon API.

func (*APIError) Error

func (e *APIError) Error() string

type ApiAppAccount

type ApiAppAccount struct {
	// AppID is the application/bot ID.
	AppID string `json:"appid"`
	// Token is the bot API key.
	Token string `json:"token"`
}

ApiAppAccount identifies a bot/app in an authentication request.

type ApiAuthenticateAppRequest

type ApiAuthenticateAppRequest struct {
	Account ApiAppAccount `json:"account"`
}

ApiAuthenticateAppRequest is the request body for bot/app authentication.

type ApiAuthenticationIdToken

type ApiAuthenticationIdToken struct {
	// IDToken is the ID token from an identity provider.
	IDToken string `json:"id_token"`
	// UserID is the user ID associated with the token.
	UserID string `json:"user_id"`
	// Username is the username associated with the token.
	Username string `json:"username"`
}

ApiAuthenticationIdToken is the request body for ID-token authentication.

type ApiChannelDescription

type ApiChannelDescription = proto.ChannelDescription

Aliases re-exporting the wire-level types used in the public API, mirroring the Api* names of the TypeScript mezon-sdk.

type ApiChannelUser

type ApiChannelUser = proto.ChannelUser

Aliases re-exporting the wire-level types used in the public API, mirroring the Api* names of the TypeScript mezon-sdk.

type ApiChannelUserList

type ApiChannelUserList = proto.ChannelUserList

Aliases re-exporting the wire-level types used in the public API, mirroring the Api* names of the TypeScript mezon-sdk.

type ApiClanUser

type ApiClanUser = proto.ClanUser

Aliases re-exporting the wire-level types used in the public API, mirroring the Api* names of the TypeScript mezon-sdk.

type ApiClanUserList

type ApiClanUserList = proto.ClanUserList

Aliases re-exporting the wire-level types used in the public API, mirroring the Api* names of the TypeScript mezon-sdk.

type ApiCreateChannelDescRequest

type ApiCreateChannelDescRequest = proto.CreateChannelDescRequest

Aliases re-exporting the wire-level types used in the public API, mirroring the Api* names of the TypeScript mezon-sdk.

type ApiMessageAttachment

type ApiMessageAttachment = proto.MessageAttachment

Aliases re-exporting the wire-level types used in the public API, mirroring the Api* names of the TypeScript mezon-sdk.

type ApiMessageMention

type ApiMessageMention = proto.MessageMention

Aliases re-exporting the wire-level types used in the public API, mirroring the Api* names of the TypeScript mezon-sdk.

type ApiSession

type ApiSession = proto.Session

Aliases re-exporting the wire-level types used in the public API, mirroring the Api* names of the TypeScript mezon-sdk.

type ApiSessionRefreshRequest

type ApiSessionRefreshRequest = proto.SessionRefreshRequest

Aliases re-exporting the wire-level types used in the public API, mirroring the Api* names of the TypeScript mezon-sdk.

type ApiUploadAttachment

type ApiUploadAttachment = proto.UploadAttachment

Aliases re-exporting the wire-level types used in the public API, mirroring the Api* names of the TypeScript mezon-sdk.

type ApiUploadAttachmentRequest

type ApiUploadAttachmentRequest = proto.UploadAttachmentRequest

Aliases re-exporting the wire-level types used in the public API, mirroring the Api* names of the TypeScript mezon-sdk.

type ApiUser

type ApiUser = proto.User

Aliases re-exporting the wire-level types used in the public API, mirroring the Api* names of the TypeScript mezon-sdk.

type AuthenticateBotConfig

type AuthenticateBotConfig struct {
	// BotID is the application/bot ID.
	BotID string `json:"bot_id"`
	// APIKey is the bot token from the developer portal.
	APIKey string `json:"api_key"`
	// GatewayURL is a custom gateway URL (optional, uses MezonGWURL if empty).
	GatewayURL string `json:"gateway_url,omitempty"`
}

AuthenticateBotConfig configures authentication of a bot (app) using the bot ID and API key from the Mezon developer portal.

type AuthenticateConfig

type AuthenticateConfig struct {
	// IDToken is the ID token from an identity provider.
	IDToken string `json:"id_token"`
	// UserID is the user ID to associate with the account.
	UserID string `json:"user_id"`
	// Username is the username for the account.
	Username string `json:"username"`
	// ServerKey is the server key for authentication (optional).
	ServerKey string `json:"serverkey,omitempty"`
	// GatewayURL is a custom gateway URL (optional, uses MezonGWURL if empty).
	GatewayURL string `json:"gateway_url,omitempty"`
}

AuthenticateConfig configures authentication of a new user.

type AuthenticationError

type AuthenticationError struct {
	Message    string
	StatusCode int
}

AuthenticationError is returned when authentication fails.

func (*AuthenticationError) Error

func (e *AuthenticationError) Error() string

type AuthenticationIdTokenResponse

type AuthenticationIdTokenResponse struct {
	// Token is the authentication token.
	Token string `json:"token"`
	// RefreshToken is used for session renewal.
	RefreshToken string `json:"refresh_token"`
	// APIURL is the API URL for the authenticated user.
	APIURL string `json:"api_url"`
	// WSURL is the WS host for the authenticated user.
	WSURL string `json:"ws_url"`
	// UserID is the user ID of the authenticated user.
	UserID string `json:"user_id"`
}

AuthenticationIdTokenResponse is the response of ID-token authentication.

type ChannelMessage

type ChannelMessage struct {
	ID                string                  `json:"id"`
	Avatar            string                  `json:"avatar,omitempty"`
	ChannelID         string                  `json:"channel_id"`
	ChannelLabel      string                  `json:"channel_label"`
	ClanID            string                  `json:"clan_id,omitempty"`
	Code              int32                   `json:"code"`
	Content           any                     `json:"content"`
	Mentions          []*ApiMessageMention    `json:"mentions,omitempty"`
	Attachments       []*ApiMessageAttachment `json:"attachments,omitempty"`
	SenderID          string                  `json:"sender_id"`
	CategoryName      string                  `json:"category_name,omitempty"`
	Username          string                  `json:"username,omitempty"`
	ClanNick          string                  `json:"clan_nick,omitempty"`
	ClanAvatar        string                  `json:"clan_avatar,omitempty"`
	DisplayName       string                  `json:"display_name,omitempty"`
	CreateTimeSeconds uint32                  `json:"create_time_seconds,omitempty"`
	UpdateTimeSeconds uint32                  `json:"update_time_seconds,omitempty"`
	Mode              int32                   `json:"mode,omitempty"`
	MessageID         string                  `json:"message_id,omitempty"`
	HideEditted       bool                    `json:"hide_editted,omitempty"`
	IsPublic          bool                    `json:"is_public,omitempty"`
	TopicID           string                  `json:"topic_id,omitempty"`
}

ChannelMessage is a message received on a channel, with content, mentions and attachments already decoded (the wire-level counterpart is proto.ChannelMessage).

type ChannelMessageHandler

type ChannelMessageHandler func(message *ChannelMessage)

ChannelMessageHandler handles channel message events.

type ChatMessageOptions

type ChatMessageOptions struct {
	Mentions         []*proto.MessageMention
	Attachments      []*proto.MessageAttachment
	References       []*proto.MessageRef
	AnonymousMessage bool
	MentionEveryone  bool
	Avatar           string
	Code             int32
	TopicID          string
	ID               string
}

ChatMessageOptions holds the optional parameters of WriteChatMessage.

type ClientInitConfig

type ClientInitConfig struct {
	// Token is the authentication token.
	Token string `json:"token"`
	// RefreshToken is used for session renewal.
	RefreshToken string `json:"refresh_token"`
	// APIURL is the API URL for the Mezon server.
	APIURL string `json:"api_url"`
	// WSURL is the WebSocket host for session connectivity.
	WSURL string `json:"ws_url"`
	// UserID is the user ID associated with the session.
	UserID string `json:"user_id"`
	// ServerKey is the server key for authentication (optional, uses
	// DefaultServerKey if empty).
	ServerKey string `json:"serverkey,omitempty"`
}

ClientInitConfig configures a LightClient created from existing tokens.

type ConnectionState

type ConnectionState int32

ConnectionState describes the socket connection lifecycle.

const (
	StateDisconnected ConnectionState = iota
	StateConnecting
	StateConnected
)

type ContentBuilder

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

ContentBuilder assembles message content from text, links, code, mentions, hashtags and emojis, tracking the UTF-16 offsets of every token so callers never count them by hand:

b := mezonlightsdk.NewContentBuilder()
b.Text("Deploy xong ").MentionHere().Text(", chi tiết: ").Link("https://ci.example.com")
ack, err := sock.WriteChatMessage(ctx, clanID, channelID, 2, true,
	b.Content(), &mezonlightsdk.ChatMessageOptions{Mentions: b.Mentions()})

func NewContentBuilder

func NewContentBuilder() *ContentBuilder

NewContentBuilder creates an empty ContentBuilder.

func (*ContentBuilder) Bold

func (b *ContentBuilder) Bold(text string) *ContentBuilder

Bold appends bold text.

func (*ContentBuilder) Code

func (b *ContentBuilder) Code(text string) *ContentBuilder

Code appends a preformatted code block.

func (*ContentBuilder) Content

func (b *ContentBuilder) Content() *MessageContent

Content returns the assembled message content.

func (*ContentBuilder) Emoji

func (b *ContentBuilder) Emoji(emojiID, display string) *ContentBuilder

Emoji appends a custom emoji; display is the shortname covering the token, e.g. ":smile:".

func (*ContentBuilder) Hashtag

func (b *ContentBuilder) Hashtag(channelID, display string) *ContentBuilder

Hashtag appends a channel reference; display is the visible text, e.g. "#general".

func (*ContentBuilder) Image

func (b *ContentBuilder) Image(img *MessageImage) *ContentBuilder

Image attaches an inline image; unlike the other tokens it does not occupy a text range.

func (b *ContentBuilder) Link(url string) *ContentBuilder

Link appends a URL rendered as a clickable link.

func (*ContentBuilder) Markup

func (b *ContentBuilder) Markup(markupType, text string) *ContentBuilder

Markup appends text covered by a markup token of the given type (MarkupTypeBold, MarkupTypeCode, ...).

func (*ContentBuilder) MentionHere

func (b *ContentBuilder) MentionHere() *ContentBuilder

MentionHere appends "@here" with the sentinel user ID, so clients render it as a user mention (blue) like the official clients do. Pair it with MentionEveryone on the send options/payload to notify the channel.

func (*ContentBuilder) MentionRole

func (b *ContentBuilder) MentionRole(roleID, display string) *ContentBuilder

MentionRole appends a role mention (rendered green by clients); display is the visible text, e.g. "@admins".

func (*ContentBuilder) MentionUser

func (b *ContentBuilder) MentionUser(userID, display string) *ContentBuilder

MentionUser appends a user mention; display is the visible text, e.g. "@alice".

func (*ContentBuilder) Mentions

func (b *ContentBuilder) Mentions() []*ApiMessageMention

Mentions returns the assembled mention entries; they travel next to the content (ChatMessageOptions.Mentions or SendMessagePayload.Mentions), not inside it.

func (*ContentBuilder) Text

func (b *ContentBuilder) Text(s string) *ContentBuilder

Text appends plain text.

type DefaultSocket

type DefaultSocket struct {
	Host    string
	Port    string
	UseSSL  bool
	Verbose bool

	// SendTimeout bounds request/response exchanges such as JoinChat.
	SendTimeout time.Duration

	// OnReconnect is called when the socket connects again after having
	// connected at least once before.
	OnReconnect func()
	// OnDisconnect is called when the connection is lost or closed.
	OnDisconnect func()
	// OnError is called for transport or decode errors.
	OnError func(err error)
	// OnHeartbeatTimeout is called when the server stops answering
	// application-level pings.
	OnHeartbeatTimeout func()
	// OnChannelMessage receives incoming channel messages.
	OnChannelMessage func(message *ChannelMessage)
	// contains filtered or unexported fields
}

DefaultSocket is a socket connection to the Mezon server speaking the protobuf realtime protocol, the Go counterpart of DefaultSocket + WebSocketAdapterPb in the TypeScript SDK.

Callback fields must be set before Connect and not mutated afterwards.

func NewDefaultSocket

func NewDefaultSocket(host, port string, useSSL, verbose bool) *DefaultSocket

NewDefaultSocket creates a socket for the given host/port. The socket is not connected until Connect is called.

func (*DefaultSocket) Connect

func (s *DefaultSocket) Connect(ctx context.Context, session *Session, createStatus bool, platform string) error

Connect dials the realtime endpoint and starts the read and heartbeat loops. If the socket is already connected it returns immediately. If ctx carries no deadline, DefaultConnectTimeout applies to the handshake.

func (*DefaultSocket) Disconnect

func (s *DefaultSocket) Disconnect(fireDisconnectEvent bool)

Disconnect closes the connection. When fireDisconnectEvent is true the OnDisconnect callback is invoked, matching the TypeScript SDK behavior.

func (*DefaultSocket) HeartbeatTimeout

func (s *DefaultSocket) HeartbeatTimeout() time.Duration

HeartbeatTimeout returns the heartbeat interval/timeout.

func (*DefaultSocket) IsOpen

func (s *DefaultSocket) IsOpen() bool

IsOpen reports whether the connection is established.

func (*DefaultSocket) JoinChat

func (s *DefaultSocket) JoinChat(ctx context.Context, clanID, channelID string, channelType int32, isPublic bool) (*proto.Channel, error)

JoinChat joins a chat channel on the server.

func (*DefaultSocket) JoinClanChat

func (s *DefaultSocket) JoinClanChat(ctx context.Context, clanID string) error

JoinClanChat joins clan-level realtime events on the server, which also registers the connection as an active clan member.

func (*DefaultSocket) LeaveChat

func (s *DefaultSocket) LeaveChat(ctx context.Context, clanID, channelID string, channelType int32, isPublic bool) error

LeaveChat leaves a chat channel on the server.

func (*DefaultSocket) SetHeartbeatTimeout

func (s *DefaultSocket) SetHeartbeatTimeout(d time.Duration)

SetHeartbeatTimeout sets the heartbeat interval/timeout used to detect a lost connection.

func (*DefaultSocket) WriteChatMessage

func (s *DefaultSocket) WriteChatMessage(ctx context.Context, clanID, channelID string, mode int32, isPublic bool, content any, opts *ChatMessageOptions) (*proto.ChannelMessageAck, error)

WriteChatMessage sends a chat message to a channel on the server. The content is JSON-encoded, matching the TypeScript SDK. Like the original, the wait for the acknowledgement is unbounded except by ctx.

type LightClient

type LightClient struct {

	// OnRefreshSession, if set, is called after each successful token
	// refresh.
	OnRefreshSession func(session *ApiSession)
	// contains filtered or unexported fields
}

LightClient provides a simplified interface for Mezon authentication and channel management.

// Initialize from existing tokens:
client, err := mezonlightsdk.InitClient(mezonlightsdk.ClientInitConfig{
	Token:        "your-token",
	RefreshToken: "your-refresh-token",
	APIURL:       "https://api.mezon.ai",
	WSURL:        "gw.mezon.ai",
	UserID:       "user-123",
})

// Or authenticate with an ID token:
client, err := mezonlightsdk.Authenticate(ctx, mezonlightsdk.AuthenticateConfig{
	IDToken:  "id-token-from-provider",
	UserID:   "user-123",
	Username: "johndoe",
})

func Authenticate

func Authenticate(ctx context.Context, config AuthenticateConfig) (*LightClient, error)

Authenticate authenticates a user with an ID token from an identity provider.

func AuthenticateBot

func AuthenticateBot(ctx context.Context, config AuthenticateBotConfig) (*LightClient, error)

AuthenticateBot authenticates a bot (app) with its bot ID and API key from the Mezon developer portal, mirroring SessionManager.authenticate in the TypeScript mezon-sdk.

func InitClient

func InitClient(config ClientInitConfig) (*LightClient, error)

InitClient initializes a LightClient from existing session tokens. Use this when you have stored tokens from a previous authentication.

func (*LightClient) Client

func (c *LightClient) Client() *MezonApi

Client returns the underlying Mezon API client.

func (*LightClient) CreateDM

func (c *LightClient) CreateDM(ctx context.Context, peerID string) (*ApiChannelDescription, error)

CreateDM creates a direct message channel with a single user.

func (*LightClient) CreateGroupDM

func (c *LightClient) CreateGroupDM(ctx context.Context, userIDs []string) (*ApiChannelDescription, error)

CreateGroupDM creates a group direct message channel with multiple users.

func (*LightClient) CreateSocket

func (c *LightClient) CreateSocket(verbose bool) *DefaultSocket

CreateSocket creates a socket with the client's configuration.

func (*LightClient) ExportSession

func (c *LightClient) ExportSession() ClientInitConfig

ExportSession exports session data for storage and later restoration via InitClient.

func (*LightClient) GetChannelDetail

func (c *LightClient) GetChannelDetail(ctx context.Context, channelID string) (*ApiChannelDescription, error)

GetChannelDetail fetches the description of a single channel.

Note: bot sessions are not permitted to call this (HTTP 403).

func (*LightClient) GetChannelUser

func (c *LightClient) GetChannelUser(ctx context.Context, clanID, channelID string, channelType int32, userID string) (*ApiChannelUser, error)

GetChannelUser finds a channel member by user ID. It returns nil if the user is not a member of the channel.

func (*LightClient) GetClanUser

func (c *LightClient) GetClanUser(ctx context.Context, clanID, userID string) (*ApiClanUser, error)

GetClanUser finds a clan member by user ID. It returns nil if the user is not a member of the clan.

func (*LightClient) IsRefreshSessionExpired

func (c *LightClient) IsRefreshSessionExpired() bool

IsRefreshSessionExpired reports whether the refresh token has expired. If it returns true, the user needs to re-authenticate.

func (*LightClient) IsSessionExpired

func (c *LightClient) IsSessionExpired() bool

IsSessionExpired reports whether the current session token has expired.

func (*LightClient) ListChannelDescs

ListChannelDescs lists the channels visible to the current user/bot.

Note: bot sessions are not permitted to call this (HTTP 403).

func (*LightClient) ListChannelUsers

func (c *LightClient) ListChannelUsers(ctx context.Context, clanID, channelID string, channelType int32) (*ApiChannelUserList, error)

ListChannelUsers lists all users that are members of a channel.

Note: bot sessions are not permitted to call this (HTTP 403).

func (*LightClient) ListClanUsers

func (c *LightClient) ListClanUsers(ctx context.Context, clanID string) (*ApiClanUserList, error)

ListClanUsers lists all users that are members of a clan.

Note: bot sessions are not permitted to call this (the gateway answers HTTP 403); bots learn member names from incoming channel messages instead.

func (*LightClient) RefreshSession

func (c *LightClient) RefreshSession(ctx context.Context) (*Session, error)

RefreshSession refreshes the current session using the refresh token. Call this before the session expires to maintain connectivity. Concurrent callers share a single in-flight refresh.

func (*LightClient) RefreshToken

func (c *LightClient) RefreshToken() string

RefreshToken returns the refresh token for storage.

func (*LightClient) Session

func (c *LightClient) Session() *Session

Session returns the underlying Mezon session.

func (*LightClient) Token

func (c *LightClient) Token() string

Token returns the authentication token for external use.

func (*LightClient) UploadAttachment

func (c *LightClient) UploadAttachment(ctx context.Context, request *ApiUploadAttachmentRequest) (*ApiUploadAttachment, error)

UploadAttachment uploads an attachment file to the Mezon server and returns the URL of the uploaded file, which can be used in messages.

func (*LightClient) UserID

func (c *LightClient) UserID() string

UserID returns the current user ID.

type LightSocket

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

LightSocket provides a simplified interface for Mezon real-time messaging.

socket := mezonlightsdk.NewLightSocket(client, client.Session())

err := socket.Connect(ctx, mezonlightsdk.SocketConnectOptions{
	OnError:      func(err error) { log.Println("socket error:", err) },
	OnDisconnect: func() { log.Println("disconnected") },
})

socket.OnChannelMessage(func(msg *mezonlightsdk.ChannelMessage) {
	log.Println("received message:", msg.Content)
})

err = socket.JoinDMChannel(ctx, "channel-123")
err = socket.SendDM(ctx, mezonlightsdk.SendMessagePayload{ChannelID: "channel-123", Content: map[string]string{"t": "Hello!"}})

func NewLightSocket

func NewLightSocket(client *LightClient, session *Session) *LightSocket

NewLightSocket creates a LightSocket bound to a client and session.

func (*LightSocket) Connect

func (s *LightSocket) Connect(ctx context.Context, options SocketConnectOptions) error

Connect connects to the Mezon real-time server.

func (*LightSocket) Disconnect

func (s *LightSocket) Disconnect()

Disconnect disconnects from the Mezon server.

func (*LightSocket) IsConnected

func (s *LightSocket) IsConnected() bool

IsConnected reports whether the socket is currently connected.

func (*LightSocket) JoinDMChannel

func (s *LightSocket) JoinDMChannel(ctx context.Context, channelID string) error

JoinDMChannel joins a DM channel to receive messages from it.

func (*LightSocket) JoinGroupChannel

func (s *LightSocket) JoinGroupChannel(ctx context.Context, channelID string) error

JoinGroupChannel joins a group channel to receive messages from it.

func (*LightSocket) LeaveDMChannel

func (s *LightSocket) LeaveDMChannel(ctx context.Context, channelID string) error

LeaveDMChannel leaves a DM channel.

func (*LightSocket) LeaveGroupChannel

func (s *LightSocket) LeaveGroupChannel(ctx context.Context, channelID string) error

LeaveGroupChannel leaves a group channel.

func (*LightSocket) OnChannelMessage

func (s *LightSocket) OnChannelMessage(handler ChannelMessageHandler) func()

OnChannelMessage registers a handler for incoming channel messages and returns a function that unsubscribes it.

func (*LightSocket) SendDM

func (s *LightSocket) SendDM(ctx context.Context, payload SendMessagePayload) error

SendDM sends a direct message to a channel.

func (*LightSocket) SendGroup

func (s *LightSocket) SendGroup(ctx context.Context, payload SendMessagePayload) error

SendGroup sends a message to a group channel.

func (*LightSocket) SetChannelMessageHandler

func (s *LightSocket) SetChannelMessageHandler(handler ChannelMessageHandler)

SetChannelMessageHandler registers a handler for incoming channel messages. Multiple handlers can be registered and all receive messages.

func (*LightSocket) SetErrorHandler

func (s *LightSocket) SetErrorHandler(handler func(err error))

SetErrorHandler sets the error handler for socket errors.

func (*LightSocket) Socket

func (s *LightSocket) Socket() (*DefaultSocket, error)

Socket returns the underlying socket instance, or an error if Connect has not been called.

type MessageContent

type MessageContent struct {
	// T is the message text.
	T string `json:"t"`
	// Mk holds markup tokens (links, code blocks, bold, ...).
	Mk []*MessageMarkup `json:"mk,omitempty"`
	// Hg holds channel hashtag references.
	Hg []*MessageHashtag `json:"hg,omitempty"`
	// Ej holds custom emoji tokens.
	Ej []*MessageEmoji `json:"ej,omitempty"`
	// Images holds inline images (webhook-style payloads).
	Images []*MessageImage `json:"images,omitempty"`
}

MessageContent is the structured content of a channel message, the same shape the Mezon clients and webhooks use ({"t": ..., "mk": [...], ...}).

func NewTextContent

func NewTextContent(text string) *MessageContent

NewTextContent builds message content from plain text, marking any URLs in it as clickable links.

type MessageEmoji

type MessageEmoji struct {
	EmojiID string `json:"emojiid"`
	S       int32  `json:"s,omitempty"`
	E       int32  `json:"e,omitempty"`
}

MessageEmoji is one custom-emoji token of message content ("ej"); S and E are UTF-16 code unit offsets (JavaScript string indices, not bytes) into the content text, covering the emoji shortname (e.g. ":smile:").

type MessageHashtag

type MessageHashtag struct {
	ChannelID string `json:"channelId"`
	S         int32  `json:"s,omitempty"`
	E         int32  `json:"e,omitempty"`
}

MessageHashtag is one channel reference of message content ("hg"); S and E are UTF-16 code unit offsets (JavaScript string indices, not bytes) into the content text.

type MessageImage

type MessageImage struct {
	// Filename is the image file name ("fn").
	Filename string `json:"fn,omitempty"`
	// Size is the file size in bytes ("sz").
	Size int32 `json:"sz,omitempty"`
	// URL is the image URL, e.g. from UploadAttachment.
	URL string `json:"url"`
	// Filetype is the MIME type ("ft"), e.g. "image/jpeg".
	Filetype string `json:"ft,omitempty"`
	// Width and Height are the image dimensions in pixels ("w"/"h").
	Width  int32 `json:"w,omitempty"`
	Height int32 `json:"h,omitempty"`
}

MessageImage is one inline image of message content ("images"), as used by webhook payloads; field names are abbreviated on the wire.

type MessageMarkup

type MessageMarkup struct {
	Type string `json:"type"`
	S    int32  `json:"s,omitempty"`
	E    int32  `json:"e,omitempty"`
}

MessageMarkup is one markup token of message content ("mk"); S and E are UTF-16 code unit offsets (JavaScript string indices, not bytes) into the content text.

func ExtractLinks(text string) []*MessageMarkup

ExtractLinks finds http(s) URLs in text and returns "lk" markup tokens for them, which clients render as clickable links. Offsets are UTF-16 code units, not bytes, matching how Mezon clients index content.

type MezonApi

type MezonApi struct {
	// ServerKey authenticates server-to-server calls (basic auth username).
	ServerKey string
	// Timeout bounds each request.
	Timeout time.Duration
	// HTTPClient performs the requests; defaults to a plain http.Client.
	HTTPClient *http.Client
	// contains filtered or unexported fields
}

MezonApi is a low-level HTTP client for the Mezon gateway, the Go counterpart of MezonApi in api.gen.ts. Request/response bodies use the protobuf wire format except for ID-token authentication, which uses JSON.

func NewMezonApi

func NewMezonApi(serverKey string, timeout time.Duration, basePath string) *MezonApi

NewMezonApi creates a client. If timeout is zero, 7 seconds is used, matching the TypeScript SDK.

func (*MezonApi) AuthenticateApp

func (a *MezonApi) AuthenticateApp(ctx context.Context, basicAuthUsername, basicAuthPassword string, body *ApiAuthenticateAppRequest) (*ApiSession, error)

AuthenticateApp authenticates a bot (app) with its API key, mirroring mezonAuthenticate in the TypeScript mezon-sdk. The request body is JSON and the response is a protobuf-encoded Session.

func (*MezonApi) AuthenticateIdToken

func (a *MezonApi) AuthenticateIdToken(ctx context.Context, basicAuthUsername, basicAuthPassword string, body *ApiAuthenticationIdToken) (*AuthenticationIdTokenResponse, error)

AuthenticateIdToken authenticates a user with an ID token from an identity provider.

func (*MezonApi) BasePath

func (a *MezonApi) BasePath() string

BasePath returns the current base URL.

func (*MezonApi) CreateChannelDesc

func (a *MezonApi) CreateChannelDesc(ctx context.Context, bearerToken string, body *ApiCreateChannelDescRequest) (*ApiChannelDescription, error)

CreateChannelDesc creates a new channel with the current user as the owner.

func (*MezonApi) GetChannelDetail

func (a *MezonApi) GetChannelDetail(ctx context.Context, bearerToken, channelID string) (*ApiChannelDescription, error)

GetChannelDetail fetches the description of a single channel.

func (*MezonApi) ListChannelDescs

func (a *MezonApi) ListChannelDescs(ctx context.Context, bearerToken string, req *proto.ListChannelDescsRequest) (*proto.ChannelDescList, error)

ListChannelDescs lists the channels visible to the current user/bot.

func (*MezonApi) ListChannelUsers

func (a *MezonApi) ListChannelUsers(ctx context.Context, bearerToken string, req *proto.ListChannelUsersRequest) (*ApiChannelUserList, error)

ListChannelUsers lists all users that are members of a channel.

func (*MezonApi) ListClanUsers

func (a *MezonApi) ListClanUsers(ctx context.Context, bearerToken, clanID string) (*ApiClanUserList, error)

ListClanUsers lists all users that are members of a clan.

func (*MezonApi) SessionRefresh

func (a *MezonApi) SessionRefresh(ctx context.Context, basicAuthUsername, basicAuthPassword string, body *ApiSessionRefreshRequest) (*ApiSession, error)

SessionRefresh refreshes a user's session using a refresh token retrieved from a previous authentication request.

func (*MezonApi) SetBasePath

func (a *MezonApi) SetBasePath(basePath string)

SetBasePath replaces the base URL, e.g. after authentication returns a user-specific endpoint.

func (*MezonApi) UploadAttachmentFile

func (a *MezonApi) UploadAttachmentFile(ctx context.Context, bearerToken string, body *ApiUploadAttachmentRequest) (*ApiUploadAttachment, error)

UploadAttachmentFile registers an attachment upload and returns the file URL that can be used in messages.

type SendMessagePayload

type SendMessagePayload struct {
	// ChannelID is the channel to send the message to.
	ChannelID string
	// Content is the message content; it is JSON-encoded before sending.
	// Plain strings and {"t": ...} maps get "lk" markup added automatically
	// for any URLs so clients render them as clickable links.
	Content any
	// Mentions holds user/role mention entries pointing into the content
	// text (see ContentBuilder).
	Mentions []*ApiMessageMention
	// Attachments holds optional file/media attachments.
	Attachments []*ApiMessageAttachment
	// MentionEveryone notifies everyone in the channel.
	MentionEveryone bool
	// HideLink, when true, leaves URLs in the content as plain text instead
	// of marking them up as clickable links.
	HideLink bool
	// Code is the optional message code.
	Code int32
}

SendMessagePayload describes a message to send.

type Session

type Session struct {
	// Token is the authorization token used to construct this session.
	Token string
	// Created reports whether the user account for this session was just
	// created.
	Created bool
	// CreatedAt is the UNIX timestamp when this session was created.
	CreatedAt int64
	// ExpiresAt is the UNIX timestamp when this session will expire.
	ExpiresAt int64
	// RefreshExpiresAt is the UNIX timestamp when the refresh token will
	// expire.
	RefreshExpiresAt int64
	// RefreshToken can be used for session token renewal.
	RefreshToken string
	// Username of the user who owns this session.
	Username string
	// UserID of the user who owns this session.
	UserID string
	// Vars holds any custom properties associated with this session.
	Vars map[string]string
	// IsRemember reports whether "Remember Me" is enabled.
	IsRemember bool
	// APIURL is the API endpoint that belongs to the user.
	APIURL string
	// WSURL is the WebSocket host that belongs to the user.
	WSURL string
	// IDToken is the ID token for zklogin, if any.
	IDToken string
}

Session is a session authenticated for a user with the Mezon server.

func NewSession

func NewSession(token, refreshToken string, created bool, apiURL, wsURL, idToken string, isRemember bool) (*Session, error)

NewSession builds a session from JWT tokens, decoding expiry and user claims from the token payloads.

func RestoreSession

func RestoreSession(token, refreshToken, apiURL, wsURL string, isRemember bool) (*Session, error)

RestoreSession restores a session from previously stored tokens.

func (*Session) IsExpired

func (s *Session) IsExpired(now time.Time) bool

IsExpired reports whether the session token has expired at the given time.

func (*Session) IsRefreshExpired

func (s *Session) IsRefreshExpired(now time.Time) bool

IsRefreshExpired reports whether the refresh token has expired at the given time.

func (*Session) Update

func (s *Session) Update(token, refreshToken string, isRemember bool) error

Update replaces the session tokens and re-decodes the JWT claims.

type SessionError

type SessionError struct {
	Message string
}

SessionError is returned when session-related operations fail.

func (*SessionError) Error

func (e *SessionError) Error() string

type SocketConnectOptions

type SocketConnectOptions struct {
	// OnError is called for socket errors.
	OnError func(err error)
	// OnDisconnect is called when the socket disconnects.
	OnDisconnect func()
	// Verbose enables verbose logging.
	Verbose bool
}

SocketConnectOptions configures a LightSocket connection.

type SocketError

type SocketError struct {
	// Code is the server error code, if the error came from the server.
	Code int32
	// Message describes the failure.
	Message string
	// Context holds additional error details reported by the server.
	Context map[string]string
}

SocketError is returned when socket operations fail, including logical errors reported by the server inside a realtime envelope.

func (*SocketError) Error

func (e *SocketError) Error() string

Directories

Path Synopsis
messagedb module
Package proto implements the protobuf wire format for the subset of mezon.api and mezon.realtime messages used by the light SDK.
Package proto implements the protobuf wire format for the subset of mezon.api and mezon.realtime messages used by the light SDK.
redisstore module

Jump to

Keyboard shortcuts

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