mezon

package module
v0.2.6 Latest Latest
Warning

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

Go to latest
Published: Jul 23, 2026 License: MIT Imports: 25 Imported by: 0

README

mezon-go

A Go port of the mezon-sdk TypeScript client for the Mezon server. It speaks the same protobuf-over-WebSocket realtime protocol and the same protobuf REST API, so a Go bot behaves like a JS bot.

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

Getting started

client, err := mezon.NewMezonClient(mezon.ClientConfig{
    BotID: os.Getenv("MEZON_BOT_ID"),
    Token: os.Getenv("MEZON_BOT_TOKEN"),
})
if err != nil { log.Fatal(err) }

client.OnChannelMessage(func(m *mezon.ChannelMessage) {
    if m.ContentText() == "ping" {
        ch, _ := client.Channels.Fetch(m.ChannelID)
        ch.Send(mezon.Text("pong"), nil)
    }
})

if err := client.Login(); err != nil { log.Fatal(err) }
select {} // the SDK runs its read/heartbeat loops in goroutines

A complete bot is in example/.

What Login does

Mirrors MezonClientCore.login:

  1. Authenticate the bot over REST (POST /v2/apps/authenticate/token, JSON body, protobuf Session response).
  2. Decode the JWT for expiry/vars, and re-target host/ws from the session's api_url/ws_url.
  3. Open the protobuf WebSocket (/ws?...&format=protobuf), then join every clan chat and build the clan/channel/user caches.

Sending messages and UTF-16

Message offsets are UTF-16 code units. The Mezon web/JS clients are JavaScript, so message-content length and mention s/e (start/end) offsets are measured in UTF-16 code units, not bytes or runes. This port does the same:

  • The 8000-character content limit is checked with UTF16Len(JSON(content)), exactly matching the JS JSON.stringify(content).length guard.
  • Use mezon.MentionSpan(text, substr) to compute a mention's S/E so a leading emoji or CJK text shifts the offset by the right amount.
reply := "👋 @bob welcome!"
s, e, _ := mezon.MentionSpan(reply, "@bob") // s=3, e=7 (the emoji is 2 units)
ch.Send(mezon.Text(reply), &mezon.SendOptions{
    Mentions: []mezon.Mention{{UserID: senderID, Username: "bob", S: s, E: e}},
})

Helpers: UTF16Len, UTF16Encode, RuneIndexToUTF16, MentionSpan.

Message actions

TextChannel.Send / SendEphemeral, and on a cached Message: Reply, Update, React, Delete. User.SendDM sends a direct message. All writes are serialized through an AsyncThrottleQueue (80/sec, like the TS SDK).

Events

Register with client.On(mezon.Event<Name>, handler) or the typed client.OnChannelMessage. channel_message delivers a friendly *mezon.ChannelMessage (content/mentions/reactions parsed); other events deliver the decoded protobuf message pointer from the rtapi/api packages.

Caching and shared state across instances

The client keeps in-memory caches (client.Clans, client.Channels, client.Users, and each channel's Messages), a port of the TS CacheManager. A miss falls back to a fetcher (REST), and inbound messages keep cached users/channels fresh. The Users and Channels caches are bounded (ClientConfig.MaxUsersCache / MaxChannelsCache, default 5000) so a long-running bot does not grow unboundedly.

For multiple bot instances, plug in an L2 store shared across replicas so they don't each refetch channel/user metadata from REST. Implement mezon.SharedStore (Get/Set/Delete of []byte with a TTL) and pass it as ClientConfig.Store; the L1 in-memory caches still hold the live objects, while the store only holds the serializable data needed to rebuild them. Lookups go L1 → L2 (store) → REST, populating both on the way back, and channel update/delete events invalidate the store entry.

A ready-made Redis adapter lives in the separate redisstore module (so the core SDK stays free of a Redis dependency):

import (
    "github.com/redis/go-redis/v9"
    "github.com/quangledang23/mezon-sdk-go/redisstore"
)

rdb := redis.NewClient(&redis.Options{Addr: "localhost:6379"})
client, _ := mezon.NewMezonClient(mezon.ClientConfig{
    BotID:    os.Getenv("MEZON_BOT_ID"),
    Token:    os.Getenv("MEZON_BOT_TOKEN"),
    Store:    redisstore.New(rdb, redisstore.WithPrefix("bot1:")),
    CacheTTL: 10 * time.Minute,
})
go get github.com/quangledang23/mezon-sdk-go/redisstore
Persistent message store

By default a channel's Messages cache is in-memory and bounded (200 entries per channel). To persist inbound messages so lookups survive restarts and eviction, implement mezon.MessageStore (SaveMessage / GetMessageByID) and pass it as ClientConfig.MessageStore. Every inbound message is saved, and a channel's Messages.Fetch falls back to the store on a miss.

A ready-made SQLite adapter (a port of the TS SDK's MessageDatabase) lives in the separate messagedb module, using the pure-Go modernc.org/sqlite driver (no cgo):

import "github.com/quangledang23/mezon-sdk-go/messagedb"

db, err := messagedb.New("") // "" => ./mezon-cache/mezon-messages-cache.db
if err != nil {
    log.Fatal(err)
}
defer db.Close()

client, _ := mezon.NewMezonClient(mezon.ClientConfig{
    BotID:        os.Getenv("MEZON_BOT_ID"),
    Token:        os.Getenv("MEZON_BOT_TOKEN"),
    MessageStore: db,
})
go get github.com/quangledang23/mezon-sdk-go/messagedb

Protobuf code generation

api/*.pb.go and rtapi/*.pb.go are generated, not hand-written. The .proto files under proto/ are reconstructed from the ts-proto output in the TS SDK by tools/tsproto2proto.js, then compiled with protoc:

node tools/tsproto2proto.js
protoc -I proto -I <wkt-include> --go_out=. --go_opt=paths=source_relative \
    proto/api/api.proto proto/rtapi/realtime.proto

Re-run both steps after the TS SDK's protobuf changes.

Not yet ported

These depend on external packages outside this repo and are intentionally left out of the first port:

  • Token transfers / ZK proofs (MMN) — the TS SDK uses the external mmn-client-js library (MmnClient, ZkClient) for sendToken, getZkProofs, ephemeral keypairs and nonces. Porting requires a Go port of that crypto library.
  • AI-agent SSE stream — the EventSourceManager / agent session events.

Local SQLite message persistence (MessageDatabase) is available via the optional messagedb module; without it messages are cached in memory only.

Documentation

Index

Constants

View Source
const (
	DefaultHost      = "gw.mezon.ai"
	DefaultPort      = "443"
	DefaultUseSSL    = true
	DefaultTimeoutMs = 7000
)

Default connection settings, port of the constants in MezonClientCore.ts.

View Source
const (
	EventChannelMessage      = "channel_message"
	EventMessageReaction     = "message_reaction_event"
	EventUserChannelRemoved  = "user_channel_removed_event"
	EventUserClanRemoved     = "user_clan_removed_event"
	EventUserChannelAdded    = "user_channel_added_event"
	EventChannelCreated      = "channel_created_event"
	EventChannelDeleted      = "channel_deleted_event"
	EventChannelUpdated      = "channel_updated_event"
	EventChannelArchive      = "channel_archive_event"
	EventRole                = "role_event"
	EventGiveCoffee          = "give_coffee_event"
	EventRoleAssign          = "role_assign_event"
	EventAddClanUser         = "add_clan_user_event"
	EventTokenSend           = "token_sent_event"
	EventClanEventCreated    = "clan_event_created"
	EventMessageButtonClick  = "message_button_clicked"
	EventStreamingJoined     = "streaming_joined_event"
	EventStreamingLeaved     = "streaming_leaved_event"
	EventDropdownBoxSelected = "dropdown_box_selected"
	EventWebrtcSignalingFwd  = "webrtc_signaling_fwd"
	EventVoiceStarted        = "voice_started_event"
	EventVoiceEnded          = "voice_ended_event"
	EventVoiceJoined         = "voice_joined_event"
	EventVoiceLeaved         = "voice_leaved_event"
	EventNotifications       = "notifications"
	EventQuickMenu           = "quick_menu_event"
	EventAIAgentEnable       = "aiagent_enabled_event"
	EventClanUpdated         = "clan_updated_event"
	EventClanProfileUpdated  = "clan_profile_updated_event"
	EventUserProfileUpdated  = "user_profile_updated_event"
	EventClanDeleted         = "clan_deleted_event"
	EventReady               = "ready"
)

Event names. These are the string keys emitted by the client, matching the Events / InternalEventsSocket enums in src/constants/enum.ts. Register a handler with MezonClient.On(<Event>, handler).

Variables

View Source
var (
	// ErrNotFound is returned when a cached entity cannot be found or fetched.
	ErrNotFound = errors.New("mezon: not found")
	// ErrSocketClosed is returned when sending on a closed socket.
	ErrSocketClosed = errors.New("mezon: socket connection has not been established yet")
	// ErrSendTimeout is returned when a socket request does not get a response in time.
	ErrSendTimeout = errors.New("mezon: timed out while waiting for a response")
)

Functions

func Enqueue added in v0.1.1

func Enqueue[T any](q *AsyncThrottleQueue, task func() (T, error)) (T, error)

Enqueue runs task on the queue and returns its result. It blocks until the task has executed.

func GenerateSnowflakeID added in v0.1.1

func GenerateSnowflakeID() string

GenerateSnowflakeID returns a unique snowflake id as a decimal string.

func IsValidUserID added in v0.1.1

func IsValidUserID(id string) bool

IsValidUserID reports whether id is a numeric snowflake id.

func MentionSpan added in v0.1.1

func MentionSpan(text, sub string) (start, end int, ok bool)

MentionSpan returns the UTF-16 [start, end) offsets of the first occurrence of sub within text, suitable for an ApiMessageMention's S/E fields. ok is false when sub is not found. end is exclusive: it is the offset one past the last code unit of sub (i.e. start + UTF16Len(sub)), so for "👋 @bob" the span of "@bob" is start=3, end=7.

func ParseURLToHostAndSSL added in v0.1.1

func ParseURLToHostAndSSL(urlStr string) (host, port string, useSSL bool, err error)

ParseURLToHostAndSSL splits a URL into host, port and SSL flag, port of parseUrlToHostAndSSL in src/utils/helper.ts.

func RuneIndexToUTF16 added in v0.1.1

func RuneIndexToUTF16(s string, runeIdx int) int

RuneIndexToUTF16 converts a rune index into s to the corresponding UTF-16 code-unit offset (the value JS would report for that position).

func Text added in v0.1.1

func Text(s string) map[string]any

Text builds a plain-text message content ({"t": s}).

func UTF16Encode added in v0.1.1

func UTF16Encode(s string) []uint16

UTF16Encode returns the UTF-16 code units of s (like JS string indexing).

func UTF16Len added in v0.1.1

func UTF16Len(s string) int

UTF16Len returns the number of UTF-16 code units in s, matching the semantics of JavaScript's String.length.

This matters for pushing messages: the Mezon web/JS clients and the server treat message-content length and mention start/end (s/e) offsets as UTF-16 code-unit indices (because JS strings are UTF-16). A naive Go port that used byte length (len(s)) or rune count (utf8.RuneCountInString) would misplace mention highlights and markdown spans for any text containing non-ASCII or astral-plane characters (emoji, CJK, etc.). Always measure message offsets with the helpers in this file.

Types

type AsyncThrottleQueue added in v0.1.1

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

AsyncThrottleQueue serializes async tasks and throttles them to a maximum number per second, port of src/mezon-client/utils/AsyncThrottleQueue.ts. Tasks run one at a time in FIFO order; enqueue blocks until the task runs and returns its result.

func NewAsyncThrottleQueue added in v0.1.1

func NewAsyncThrottleQueue(maxPerSecond int) *AsyncThrottleQueue

NewAsyncThrottleQueue creates a queue allowing maxPerSecond tasks per second (defaults to 80 when <= 0).

type Attachment added in v0.1.1

type Attachment struct {
	Filename  string `json:"filename,omitempty"`
	Size      int    `json:"size,omitempty"`
	URL       string `json:"url,omitempty"`
	Filetype  string `json:"filetype,omitempty"`
	Width     int    `json:"width,omitempty"`
	Height    int    `json:"height,omitempty"`
	Thumbnail string `json:"thumbnail,omitempty"`
	Duration  int    `json:"duration,omitempty"`
}

Attachment is a message attachment.

type CacheManager added in v0.1.1

type CacheManager[K comparable, V any] struct {
	// contains filtered or unexported fields
}

CacheManager is a thread-safe, insertion-ordered cache with a fetcher used to lazily load missing entries, port of CacheManager + Collection in src/mezon-client/utils. maxSize <= 0 means unbounded.

func NewCacheManager added in v0.1.1

func NewCacheManager[K comparable, V any](fetcher func(K) (V, error), maxSize int) *CacheManager[K, V]

NewCacheManager creates a cache. fetcher may be nil (Fetch then only returns cached values).

func (*CacheManager[K, V]) Delete added in v0.1.1

func (c *CacheManager[K, V]) Delete(id K) bool

Delete removes id from the cache.

func (*CacheManager[K, V]) Fetch added in v0.1.1

func (c *CacheManager[K, V]) Fetch(id K) (V, error)

Fetch returns the cached value, loading it via the fetcher on a miss.

func (*CacheManager[K, V]) Get added in v0.1.1

func (c *CacheManager[K, V]) Get(id K) (V, bool)

Get returns the cached value and whether it was present.

func (*CacheManager[K, V]) Set added in v0.1.1

func (c *CacheManager[K, V]) Set(id K, value V)

Set stores value under id, evicting the oldest entry when maxSize is reached.

func (*CacheManager[K, V]) Size added in v0.1.1

func (c *CacheManager[K, V]) Size() int

Size returns the number of cached entries.

func (*CacheManager[K, V]) Values added in v0.1.1

func (c *CacheManager[K, V]) Values() []V

Values returns a snapshot of cached values in insertion order.

type ChannelManager added in v0.1.1

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

ChannelManager handles DM-channel discovery and creation, port of src/mezon-client/manager/channel_manager.ts.

func (*ChannelManager) CreateDMChannel added in v0.1.1

func (m *ChannelManager) CreateDMChannel(userID string) (*api.ChannelDescription, error)

CreateDMChannel creates (or returns) a DM channel with the user, port of createDMchannel. It joins the channel realtime chat on success.

func (*ChannelManager) GetAllDMChannelDescs added in v0.1.2

func (m *ChannelManager) GetAllDMChannelDescs() []*api.ChannelDescription

GetAllDMChannelDescs returns the discovered DM channel descriptions, port of getAllDmChannelDescs.

func (*ChannelManager) GetAllDMChannels added in v0.1.1

func (m *ChannelManager) GetAllDMChannels() map[string]string

GetAllDMChannels returns the discovered DM channel map (user id -> channel id).

func (*ChannelManager) InitAllDMChannels added in v0.1.1

func (m *ChannelManager) InitAllDMChannels(sessionToken string) error

InitAllDMChannels loads existing DM channels, port of initAllDmChannels. It records both the user->channel map and the raw channel descriptions (so the client can pre-cache them as TextChannels).

type ChannelMessage

type ChannelMessage struct {
	ID                string          `json:"id"`
	ChannelID         string          `json:"channel_id"`
	ClanID            string          `json:"clan_id"`
	Code              int32           `json:"code"`
	SenderID          string          `json:"sender_id"`
	Username          string          `json:"username"`
	Avatar            string          `json:"avatar"`
	Content           json.RawMessage `json:"content"`
	Reactions         []Reaction      `json:"reactions"`
	Mentions          []Mention       `json:"mentions"`
	Attachments       []Attachment    `json:"attachments"`
	References        []MessageRef    `json:"references"`
	ReferencedMessage json.RawMessage `json:"referenced_message"`
	MessageID         string          `json:"message_id"`
	ChannelLabel      string          `json:"channel_label"`
	CategoryName      string          `json:"category_name"`
	DisplayName       string          `json:"display_name"`
	ClanNick          string          `json:"clan_nick"`
	ClanAvatar        string          `json:"clan_avatar"`
	Mode              int32           `json:"mode"`
	HideEditted       bool            `json:"hide_editted"`
	IsPublic          bool            `json:"is_public"`
	TopicID           string          `json:"topic_id"`
	CreateTimeSeconds uint32          `json:"create_time_seconds"`
	UpdateTimeSeconds uint32          `json:"update_time_seconds"`
}

ChannelMessage is an inbound chat message, port of the ChannelMessage interface in src/socket.ts. Content holds the raw JSON content string; the reactions/mentions/attachments/references fields arrive as JSON blobs on the wire and are parsed here (mirroring CreateChannelMessageFromEvent).

func (*ChannelMessage) ContentText added in v0.1.1

func (m *ChannelMessage) ContentText() string

ContentText returns the "t" text field of the content, if present.

type ChannelStreamMode added in v0.1.1

type ChannelStreamMode int

ChannelStreamMode mirrors src/constants/enum.ts ChannelStreamMode.

const (
	StreamModeChannel ChannelStreamMode = 2
	StreamModeGroup   ChannelStreamMode = 3
	StreamModeDM      ChannelStreamMode = 4
	StreamModeClan    ChannelStreamMode = 5
	StreamModeThread  ChannelStreamMode = 6
)

func ConvertChannelTypeToChannelMode added in v0.1.1

func ConvertChannelTypeToChannelMode(channelType int) ChannelStreamMode

ConvertChannelTypeToChannelMode maps a channel type to its stream mode, port of convertChanneltypeToChannelMode in src/utils/helper.ts.

type ChannelType added in v0.1.1

type ChannelType int

ChannelType mirrors src/constants/enum.ts ChannelType.

const (
	ChannelTypeChannel      ChannelType = 1
	ChannelTypeGroup        ChannelType = 2
	ChannelTypeDM           ChannelType = 3
	ChannelTypeGmeetVoice   ChannelType = 4
	ChannelTypeForum        ChannelType = 5
	ChannelTypeStreaming    ChannelType = 6
	ChannelTypeThread       ChannelType = 7
	ChannelTypeApp          ChannelType = 8
	ChannelTypeAnnouncement ChannelType = 9
	ChannelTypeMezonVoice   ChannelType = 10
)

type Clan added in v0.1.1

type Clan struct {
	ID               string
	Name             string
	WelcomeChannelID string
	ClanName         string
	Channels         *CacheManager[string, *TextChannel]
	SessionToken     string
	ClientID         string
	// contains filtered or unexported fields
}

Clan is a Mezon clan (server/guild), port of src/mezon-client/structures/Clan.ts.

func (*Clan) AddRolesToChannel added in v0.2.6

func (c *Clan) AddRolesToChannel(channelID string, roleIDs []string) error

AddRolesToChannel grants roles access to a private channel.

func (*Clan) CreateChannel added in v0.2.2

func (c *Clan) CreateChannel(d CreateChannelData) (*api.ChannelDescription, error)

CreateChannel creates a channel in the clan and caches it as a live TextChannel. Bulk creation is one call per channel — the server has no batch endpoint.

func (*Clan) CreateRole added in v0.2.6

func (c *Clan) CreateRole(req *api.CreateRoleRequest) (*api.Role, error)

CreateRole creates a role in this clan and returns it. A zero req.ClanId is filled in from the clan.

func (*Clan) DeleteChannel added in v0.2.2

func (c *Clan) DeleteChannel(channelID string) error

DeleteChannel deletes a channel from the clan and evicts it from the caches.

func (*Clan) DeleteRole added in v0.2.6

func (c *Clan) DeleteRole(roleID string) error

DeleteRole deletes a role from this clan.

func (*Clan) ListChannelVoiceUsers added in v0.1.1

func (c *Clan) ListChannelVoiceUsers(limit int32) (*api.VoiceChannelUserList, error)

ListChannelVoiceUsers lists users in the clan's voice channels, port of Clan.listChannelVoiceUsers.

func (*Clan) ListPermissions added in v0.2.6

func (c *Clan) ListPermissions() (*api.PermissionList, error)

ListPermissions lists the permission definitions known to the server, for mapping slugs like "send-message" to permission ids.

func (*Clan) ListRoles added in v0.1.1

func (c *Clan) ListRoles(limit, state int32, cursor string) (*api.RoleListEventResponse, error)

ListRoles lists clan roles, port of Clan.listRoles.

func (*Clan) LoadChannels added in v0.1.1

func (c *Clan) LoadChannels() error

LoadChannels loads the clan's text channels once, port of Clan.loadChannels.

func (*Clan) ReloadChannels added in v0.2.5

func (c *Clan) ReloadChannels() error

ReloadChannels re-fetches the clan's channels and merges them into the caches even when they were already loaded, so a reconnect picks up channels created or changed while the socket was down, port of Clan.reloadChannels (mezon-js PR #1129).

func (*Clan) SetRoleChannelPermission added in v0.2.6

func (c *Clan) SetRoleChannelPermission(req *api.UpdateRoleChannelRequest) error

SetRoleChannelPermission sets per-channel permission overrides for a role (req.RoleId) or a user (req.UserId).

func (*Clan) UpdateChannelPrivate added in v0.2.6

func (c *Clan) UpdateChannelPrivate(channelID string, private bool, roleIDs, userIDs []string) error

UpdateChannelPrivate makes a channel private (private=true) or public. roleIDs and userIDs keep access when turning private; both may be nil.

func (*Clan) UpdateRole added in v0.1.1

func (c *Clan) UpdateRole(req *api.UpdateRoleRequest) error

UpdateRole updates a clan role, port of Clan.updateRole.

type ClientConfig added in v0.1.1

type ClientConfig struct {
	BotID   string
	Token   string
	Host    string
	Port    string
	UseSSL  *bool // nil => default (true)
	Timeout time.Duration

	// Transport selects the realtime wire transport: TransportTCP (abridged
	// TLS/TCP, the default when empty) or TransportWebSocket.
	Transport TransportKind
	// TLSInsecureSkipVerify disables certificate verification for the TCP
	// transport; dev gateways use self-signed certificates.
	TLSInsecureSkipVerify bool

	// Store, when non-nil, is an L2 cache shared across bot instances (e.g.
	// Redis). Channel and user lookups consult it before hitting the REST API
	// and populate it on a miss, so replicas avoid redundant REST calls. The
	// in-memory caches remain the L1 (live objects); Store only holds the
	// serializable data needed to rebuild them. nil => in-memory only.
	Store SharedStore
	// CacheTTL bounds how long entries live in Store (<= 0 => 5 minutes).
	CacheTTL time.Duration
	// MaxUsersCache / MaxChannelsCache bound the in-memory L1 caches so a
	// long-running bot does not grow unboundedly (<= 0 => 5000 each).
	MaxUsersCache    int
	MaxChannelsCache int

	// MessageStore, when non-nil, persists every inbound message and backs the
	// per-channel Messages cache on a miss (port of the SQLite MessageDatabase).
	// A SQLite implementation is available in the messagedb submodule. nil =>
	// messages are cached in memory only.
	MessageStore MessageStore
}

ClientConfig configures a MezonClient. BotID and Token are required.

type Content added in v0.1.1

type Content = any

Content is a message content payload. It is serialized to JSON and sent as the message's `content` string on the wire (mirroring `content: any` in the TS SDK). Use Text for a plain text message, or pass any struct/map for embeds, components, buzz, etc.

type CreateChannelData added in v0.2.2

type CreateChannelData struct {
	Label string
	// Type is one of the ChannelType* constants; 0 => ChannelTypeChannel.
	Type    int
	Private bool
	// CategoryID places the channel in a category; "" => the clan default.
	CategoryID string
	// UserIDs invites members, typically for private channels.
	UserIDs []string
	// ParentID makes the channel a thread under the given channel.
	ParentID string
}

CreateChannelData configures Clan.CreateChannel.

type DefaultSocket

type DefaultSocket struct {
	Verbose bool

	// Transport selects the wire transport for the next Connect; empty means
	// TransportTCP. TLSInsecureSkipVerify disables certificate verification for
	// the TCP transport (dev gateways use self-signed certs).
	Transport             TransportKind
	TLSInsecureSkipVerify bool

	// TcpURL is the dedicated abridged-TCP endpoint from Session.tcp_url. When
	// set, the TCP transport dials it instead of deriving an address from the
	// websocket URL / host.
	TcpURL string

	// optional lifecycle callbacks
	OnDisconnect       func(reason string)
	OnError            func(err error)
	OnHeartbeatTimeout func()
	// contains filtered or unexported fields
}

DefaultSocket is a realtime connection to the Mezon server, port of DefaultSocket + the transport adapters in the TS SDK. It encodes/decodes rtapi.Envelope frames over a transportConn (abridged TCP by default, WebSocket opt-in) and correlates request/response pairs by cid.

func NewDefaultSocket

func NewDefaultSocket(wsURL, host, port string, useSSL bool, emit func(string, any)) *DefaultSocket

NewDefaultSocket creates a socket. wsURL is the host portion used to build the websocket URL (typically session.WsURL); when empty, host[:port] is used.

func (*DefaultSocket) Close added in v0.1.1

func (s *DefaultSocket) Close()

Close shuts down the connection.

func (*DefaultSocket) Connect

func (s *DefaultSocket) Connect(session *Session, createStatus bool) error

Connect establishes the connection using the session token.

func (*DefaultSocket) DeleteChannelMessage added in v0.2.1

func (s *DefaultSocket) DeleteChannelMessage(d RemoveMessageData) (*rtapi.ChannelMessageAck, error)

DeleteChannelMessage deletes a message via an API request over the socket, port of socket.deleteChannelMessage (which replaced removeChatMessage as the path used by socket_manager in mezon-js v2.8.50).

func (*DefaultSocket) IsOpen

func (s *DefaultSocket) IsOpen() bool

IsOpen reports whether the socket is connected.

func (*DefaultSocket) JoinChat

func (s *DefaultSocket) JoinChat(clanID, channelID string, channelType int, isPublic bool) (*rtapi.Channel, error)

JoinChat joins a channel's realtime chat, port of socket.joinChat.

func (*DefaultSocket) JoinClanChat

func (s *DefaultSocket) JoinClanChat(clanID string) (*rtapi.ClanJoin, error)

JoinClanChat joins a clan's realtime chat, port of socket.joinClanChat.

func (*DefaultSocket) LeaveChat

func (s *DefaultSocket) LeaveChat(clanID, channelID string, channelType int, isPublic bool) error

LeaveChat leaves a channel's realtime chat, port of socket.leaveChat.

func (*DefaultSocket) RemoveChatMessage added in v0.1.1

func (s *DefaultSocket) RemoveChatMessage(d RemoveMessageData) (*rtapi.ChannelMessageAck, error)

RemoveChatMessage deletes a message, port of socket.removeChatMessage.

func (*DefaultSocket) UpdateChannelMessage added in v0.2.1

func (s *DefaultSocket) UpdateChannelMessage(d UpdateMessageData) (*rtapi.ChannelMessageAck, error)

UpdateChannelMessage edits a previously sent message via an API request over the socket, port of socket.updateChannelMessage (which replaced updateChatMessage as the path used by socket_manager in mezon-js v2.8.50).

func (*DefaultSocket) UpdateChatMessage added in v0.1.1

func (s *DefaultSocket) UpdateChatMessage(d UpdateMessageData) (*rtapi.ChannelMessageAck, error)

UpdateChatMessage edits a previously sent message, port of socket.updateChatMessage.

func (*DefaultSocket) WriteChatMessage

func (s *DefaultSocket) WriteChatMessage(d ReplyMessageData) (*rtapi.ChannelMessageAck, error)

WriteChatMessage sends a chat message, port of socket.writeChatMessage (with the content-length guard from socket_manager.writeChatMessage). Content is JSON-serialized and its length validated in UTF-16 code units.

func (*DefaultSocket) WriteEphemeralMessage added in v0.1.1

func (s *DefaultSocket) WriteEphemeralMessage(d EphemeralMessageData) (*api.ChannelMessage, error)

WriteEphemeralMessage sends an ephemeral message visible only to receivers, port of socket.writeEphemeralMessage.

func (*DefaultSocket) WriteMessageReaction added in v0.1.1

func (s *DefaultSocket) WriteMessageReaction(d ReactMessageData) (*api.MessageReaction, error)

WriteMessageReaction adds or removes a reaction, port of socket.writeMessageReaction.

type EphemeralMessageData added in v0.1.1

type EphemeralMessageData struct {
	ReceiverIDs      []string
	ClanID           string
	ChannelID        string
	ChannelType      int
	Mode             int
	IsPublic         bool
	Content          Content
	Mentions         []Mention
	Attachments      []Attachment
	References       []MessageRef
	AnonymousMessage bool
	MentionEveryone  bool
	Avatar           string
	Code             int
	TopicID          string
	MessageID        string
}

EphemeralMessageData is the payload for an ephemeral message.

type Handler added in v0.1.1

type Handler func(payload any)

Handler receives an emitted event payload. Callers type-assert payload to the concrete event type documented on each MezonClient.On* method.

type Mention added in v0.1.1

type Mention struct {
	UserID            string `json:"user_id,omitempty"`
	RoleID            string `json:"role_id,omitempty"`
	Username          string `json:"username,omitempty"`
	Rolename          string `json:"rolename,omitempty"`
	S                 int    `json:"s"`
	E                 int    `json:"e"`
	CreateTimeSeconds uint32 `json:"create_time_seconds,omitempty"`
}

Mention is a user/role mention with UTF-16 start/end offsets into the message text (S/E). The Mezon clients compute these offsets in UTF-16 code units; use MentionSpan to derive them from text so they line up across clients.

type Message added in v0.1.1

type Message struct {
	ID                string
	ClanID            string
	ChannelID         string
	SenderID          string
	Content           json.RawMessage
	Mentions          []Mention
	Attachments       []Attachment
	References        []MessageRef
	Reactions         []Reaction
	TopicID           string
	CreateTimeSeconds uint32
	UpdateTimeSeconds uint32
	Code              int
	Username          string
	CreateTime        string
	UpdateTime        string
	Persistent        bool
	Mode              int
	Channel           *TextChannel
	// contains filtered or unexported fields
}

Message is a cached chat message with reply/edit/react/delete actions, port of src/mezon-client/structures/Message.ts.

func (*Message) Delete added in v0.1.1

func (m *Message) Delete() (*rtapi.ChannelMessageAck, error)

Delete removes this message, port of Message.delete.

func (*Message) MessageID added in v0.1.2

func (m *Message) MessageID() string

MessageID returns the message id (alias of ID), port of the Message.message_id getter in Message.ts.

func (*Message) React added in v0.1.1

func (m *Message) React(p ReactPayload) (*api.MessageReaction, error)

React adds or removes a reaction, port of Message.react.

func (*Message) Reply added in v0.1.1

func (m *Message) Reply(content Content, opts *SendOptions) (*Message, error)

Reply replies to this message, port of Message.reply. It returns the created Message built from the send ack. opts may be nil.

func (*Message) Update added in v0.1.1

func (m *Message) Update(content Content, mentions []Mention, attachments []Attachment) (*Message, error)

Update edits this message, port of Message.update. It mutates this Message with the new content/mentions/attachments, refreshes it in the channel cache, and returns it.

type MessageRef added in v0.1.1

type MessageRef struct {
	MessageID                string `json:"message_id,omitempty"`
	MessageRefID             string `json:"message_ref_id,omitempty"`
	Content                  string `json:"content,omitempty"`
	HasAttachment            bool   `json:"has_attachment,omitempty"`
	RefType                  int    `json:"ref_type,omitempty"`
	MessageSenderID          string `json:"message_sender_id,omitempty"`
	MessageSenderUsername    string `json:"message_sender_username,omitempty"`
	MessageSenderAvatar      string `json:"message_sender_avatar,omitempty"`
	MessageSenderClanNick    string `json:"message_sender_clan_nick,omitempty"`
	MessageSenderDisplayName string `json:"message_sender_display_name,omitempty"`
}

MessageRef references another message (used for replies/quotes).

type MessageStore added in v0.1.2

type MessageStore interface {
	// SaveMessage persists (inserts or replaces) a message keyed by
	// (message id, channel id, clan id).
	SaveMessage(m *ChannelMessage) error
	// GetMessageByID loads a previously saved message, or returns (nil, nil)
	// when absent.
	GetMessageByID(messageID, channelID, clanID string) (*ChannelMessage, error)
}

MessageStore is an optional persistent store for inbound chat messages, port of src/sqlite/MessageDatabase.ts. When configured on ClientConfig, the client saves every inbound ChannelMessage and a channel's Messages cache falls back to it on a miss, so message lookups survive process restarts and eviction from the bounded in-memory cache.

The core module does not ship an implementation to avoid forcing a storage dependency on every consumer; a SQLite-backed implementation lives in the messagedb submodule (github.com/quangledang23/mezon-sdk-go/messagedb). Implementations must be safe for concurrent use. GetMessageByID returns (nil, nil) or a non-nil error for a miss; both are treated as "not found".

type MezonApi

type MezonApi struct {
	APIKey   string
	BasePath string
	Timeout  time.Duration
	// contains filtered or unexported fields
}

MezonApi is the REST client for the Mezon server, port of src/api.ts. Request and response bodies are protobuf (Content-Type/Accept: application/proto) posted to the /mezon.api.Mezon/<Method> endpoints, except authentication which posts JSON.

func NewMezonApi

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

NewMezonApi creates a REST client.

func (*MezonApi) AddQuickMenuAccess added in v0.1.1

func (a *MezonApi) AddQuickMenuAccess(bearer string, req *api.QuickMenuAccess) error

AddQuickMenuAccess adds a quick-menu entry, port of addQuickMenuAccess.

func (*MezonApi) AddRolesChannelDesc added in v0.2.6

func (a *MezonApi) AddRolesChannelDesc(bearer string, req *api.AddRoleChannelDescRequest) error

AddRolesChannelDesc grants roles access to a private channel, port of addRolesChannelDesc.

func (*MezonApi) AttachSocket added in v0.2.2

func (a *MezonApi) AttachSocket(s *DefaultSocket)

AttachSocket routes this client's /mezon.api.Mezon/ requests over the given realtime socket whenever it is open (see doProtoSocket). MezonClient wires this up automatically; it is exported for low-level socket users.

func (*MezonApi) Call added in v0.2.5

func (a *MezonApi) Call(bearer, apiName string, req, resp proto.Message) error

Call invokes an arbitrary /mezon.api.Mezon/ endpoint by API name (see apiname.go for the known names), for endpoints without a dedicated wrapper. req/resp may be nil for empty request/response bodies. Like every API call it rides the realtime socket when open and falls back to HTTP.

func (*MezonApi) CreateChannelDesc

func (a *MezonApi) CreateChannelDesc(bearer string, req *api.CreateChannelDescRequest) (*api.ChannelDescription, error)

CreateChannelDesc creates a channel, port of createChannelDesc.

func (*MezonApi) CreateRole added in v0.2.6

func (a *MezonApi) CreateRole(bearer string, req *api.CreateRoleRequest) (*api.Role, error)

CreateRole creates a clan role and returns it, port of createRole.

func (*MezonApi) DeleteChannelDesc added in v0.2.2

func (a *MezonApi) DeleteChannelDesc(bearer, clanID, channelID string) error

DeleteChannelDesc deletes a channel, port of deleteChannelDesc.

func (*MezonApi) DeleteRole added in v0.2.6

func (a *MezonApi) DeleteRole(bearer, roleID, clanID string) error

DeleteRole deletes a clan role, port of deleteRole.

func (*MezonApi) GetListPermission added in v0.2.6

func (a *MezonApi) GetListPermission(bearer string) (*api.PermissionList, error)

GetListPermission lists the permission definitions (id/slug/title) known to the server, port of getListPermission.

func (*MezonApi) ListChannelDescs

func (a *MezonApi) ListChannelDescs(bearer string, channelType int32, clanID string, limit, state int32, cursor string, isMobile bool) (*api.ChannelDescList, error)

ListChannelDescs lists channels, port of listChannelDescs.

func (*MezonApi) ListChannelDetail added in v0.1.1

func (a *MezonApi) ListChannelDetail(bearer, channelID string) (*api.ChannelDescription, error)

ListChannelDetail returns a channel's detail, port of listChannelDetail.

func (*MezonApi) ListChannelVoiceUsers added in v0.1.1

func (a *MezonApi) ListChannelVoiceUsers(bearer, clanID string, limit int32) (*api.VoiceChannelUserList, error)

ListChannelVoiceUsers lists users in voice channels, port of listChannelVoiceUsers.

func (*MezonApi) ListClanDescs added in v0.1.1

func (a *MezonApi) ListClanDescs(bearer string, limit, state int32, cursor string) (*api.ClanDescList, error)

ListClanDescs lists the clans the bot belongs to, port of listClanDescs.

func (*MezonApi) ListQuickMenuAccess added in v0.1.1

func (a *MezonApi) ListQuickMenuAccess(bearer, botID, channelID string, menuType int32) (*api.QuickMenuAccessList, error)

ListQuickMenuAccess lists quick-menu entries, port of listQuickMenuAccess.

func (*MezonApi) ListRoles added in v0.1.1

func (a *MezonApi) ListRoles(bearer, clanID string, limit, state int32, cursor string) (*api.RoleListEventResponse, error)

ListRoles lists clan roles, port of listRoles.

func (*MezonApi) MezonAuthenticate added in v0.1.1

func (a *MezonApi) MezonAuthenticate(botID, apiKey string) (*api.Session, error)

MezonAuthenticate authenticates an app/bot and returns its session, port of mezonAuthenticate. The body is JSON, the response protobuf.

func (*MezonApi) PlayMedia added in v0.1.1

func (a *MezonApi) PlayMedia(bearer string, body map[string]any) (map[string]any, error)

PlayMedia posts a play-media request to the streaming server, port of playMedia.

func (*MezonApi) SendChannelMessage added in v0.2.5

func (a *MezonApi) SendChannelMessage(bearer string, req *rtapi.ChannelMessageSend) (*rtapi.ChannelMessageAck, error)

SendChannelMessage sends a chat message via the API endpoint, port of client.sendChannelMessageApi (mezon-js v2.15.66). Like the other API methods it rides the realtime socket when open and falls back to HTTP — making it a way to send messages while the socket is down. req.Content must already be the JSON-serialized content string (see marshalContent).

func (*MezonApi) SetRoleChannelPermission added in v0.2.6

func (a *MezonApi) SetRoleChannelPermission(bearer string, req *api.UpdateRoleChannelRequest) error

SetRoleChannelPermission sets per-channel permission overrides for a role or user, port of setRoleChannelPermission.

func (*MezonApi) UpdateChannelPrivate added in v0.2.6

func (a *MezonApi) UpdateChannelPrivate(bearer string, req *api.ChangeChannelPrivateRequest) error

UpdateChannelPrivate toggles a channel between public and private, port of updateChannelPrivate. RoleIds/UserIds grant access when turning private.

func (*MezonApi) UpdateRole added in v0.1.1

func (a *MezonApi) UpdateRole(bearer string, req *api.UpdateRoleRequest) error

UpdateRole updates a role, port of updateRole.

type MezonClient added in v0.1.1

type MezonClient struct {
	Token    string
	ClientID string
	Host     string
	Port     string
	UseSSL   bool
	Timeout  time.Duration

	Transport             TransportKind
	TLSInsecureSkipVerify bool

	Clans    *CacheManager[string, *Clan]
	Channels *CacheManager[string, *TextChannel]
	Users    *CacheManager[string, *User]
	// contains filtered or unexported fields
}

MezonClient is the high-level Mezon bot client, port of MezonClient + MezonClientCore. Construct with NewMezonClient, register event handlers with On*/On, then call Login.

func NewMezonClient added in v0.1.1

func NewMezonClient(cfg ClientConfig) (*MezonClient, error)

NewMezonClient creates a client from config, applying defaults.

func (*MezonClient) ChannelManager added in v0.1.1

func (c *MezonClient) ChannelManager() *ChannelManager

ChannelManager returns the DM channel manager.

func (*MezonClient) Close added in v0.1.1

func (c *MezonClient) Close()

Close shuts down the socket and prevents reconnection.

func (*MezonClient) Login added in v0.1.1

func (c *MezonClient) Login() error

Login authenticates the bot, connects the socket and joins all clans, port of MezonClientCore.login/handleClientLogin. It returns once the client is ready.

func (*MezonClient) On added in v0.1.1

func (c *MezonClient) On(event string, h Handler)

On registers a handler for an event (see the Event* constants). The payload type depends on the event; for EventChannelMessage it is *ChannelMessage, for other events it is the decoded protobuf message pointer.

func (*MezonClient) OnChannelMessage added in v0.1.1

func (c *MezonClient) OnChannelMessage(h func(*ChannelMessage))

OnChannelMessage registers a handler for inbound chat messages.

func (*MezonClient) OnReady added in v0.1.1

func (c *MezonClient) OnReady(h func())

OnReady registers a handler invoked once the client has logged in and joined.

func (*MezonClient) Socket added in v0.1.1

func (c *MezonClient) Socket() *DefaultSocket

Socket returns the underlying socket for advanced/raw realtime calls.

type ReactMessageData added in v0.1.1

type ReactMessageData struct {
	ID              string
	ClanID          string
	ChannelID       string
	ChannelType     int
	Mode            int
	IsPublic        bool
	MessageID       string
	EmojiID         string
	Emoji           string
	Count           int
	MessageSenderID string
	ActionDelete    bool
}

ReactMessageData is the payload for reacting to a message.

type ReactPayload added in v0.1.1

type ReactPayload struct {
	ID           string
	EmojiID      string
	Emoji        string
	Count        int
	ActionDelete bool
}

ReactPayload is the input to Message.React.

type Reaction added in v0.1.1

type Reaction struct {
	ID              string `json:"id,omitempty"`
	EmojiID         string `json:"emoji_id,omitempty"`
	Emoji           string `json:"emoji,omitempty"`
	SenderID        string `json:"sender_id,omitempty"`
	SenderName      string `json:"sender_name,omitempty"`
	Action          bool   `json:"action,omitempty"`
	Count           int    `json:"count,omitempty"`
	MessageSenderID string `json:"message_sender_id,omitempty"`
}

Reaction is a message reaction.

type RemoveMessageData added in v0.1.1

type RemoveMessageData struct {
	ClanID        string
	ChannelID     string
	ChannelType   int
	Mode          int
	IsPublic      bool
	MessageID     string
	TopicID       string
	HasAttachment bool
}

RemoveMessageData is the payload for deleting a message.

type ReplyMessageData added in v0.1.1

type ReplyMessageData struct {
	ClanID           string
	ChannelID        string
	ChannelType      int
	Mode             int
	IsPublic         bool
	Content          Content
	Mentions         []Mention
	Attachments      []Attachment
	References       []MessageRef
	AnonymousMessage bool
	MentionEveryone  bool
	Avatar           string
	Code             int
	TopicID          string
}

ReplyMessageData is the payload for writing/replying a chat message.

type SendOptions added in v0.1.1

type SendOptions struct {
	Mentions        []Mention
	Attachments     []Attachment
	References      []MessageRef
	MentionEveryone bool
	Anonymous       bool
	TopicID         string
	Code            int
}

SendOptions carries the optional parameters for sending a message.

type Session

type Session struct {
	Token            string         `json:"token"`
	RefreshToken     string         `json:"refresh_token"`
	CreatedAt        int64          `json:"created_at"`
	ExpiresAt        int64          `json:"expires_at"`
	RefreshExpiresAt int64          `json:"refresh_expires_at"`
	UserID           string         `json:"user_id"`
	Vars             map[string]any `json:"vars"`
	APIURL           string         `json:"api_url"`
	IDToken          string         `json:"id_token"`
	WsURL            string         `json:"ws_url"`
	// TcpURL is the dedicated abridged-TCP gateway endpoint returned by the
	// server (Session.tcp_url, "abriged url"). Empty on older servers; the
	// TCP transport then falls back to WsURL / host:port.
	TcpURL string `json:"tcp_url"`
}

Session is a user session authenticated with the Mezon server. It mirrors the Session class in src/session.ts: the token is a JWT whose payload carries the expiry and custom vars.

func NewSession

func NewSession(token, refreshToken, userID, apiURL, idToken, wsURL string) (*Session, error)

NewSession builds a Session from an authenticate response, decoding the JWT to populate the expiry and vars (port of Session.constructor + update).

func (*Session) IsExpired

func (s *Session) IsExpired(now int64) bool

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

func (*Session) IsRefreshExpired

func (s *Session) IsRefreshExpired(now int64) bool

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

type SharedStore added in v0.1.1

type SharedStore interface {
	Get(ctx context.Context, key string) (value []byte, ok bool, err error)
	Set(ctx context.Context, key string, value []byte, ttl time.Duration) error
	Delete(ctx context.Context, key string) error
}

SharedStore is an optional L2 cache backend that can be shared across bot instances (e.g. backed by Redis). It stores opaque bytes keyed by string; the SDK serializes only the data needed to rebuild a channel/user, never the live objects (which hold per-process socket/queue references). Implementations must be safe for concurrent use. A miss returns (nil, false, nil); transient backend errors are returned and treated as a miss by the SDK.

type TextChannel added in v0.1.1

type TextChannel struct {
	ID           string
	Name         string
	IsPrivate    bool
	ChannelType  int
	CategoryID   string
	CategoryName string
	ParentID     string
	MeetingCode  string
	Clan         *Clan
	Messages     *CacheManager[string, *Message]
	// contains filtered or unexported fields
}

TextChannel is a chat channel, port of src/mezon-client/structures/TextChannel.ts.

func (*TextChannel) Send added in v0.1.1

func (c *TextChannel) Send(content Content, opts *SendOptions) (*Message, error)

Send sends a message to the channel, port of TextChannel.send. The content is JSON-serialized and length-validated in UTF-16 code units. It returns the created Message built from the send ack. opts may be nil.

func (*TextChannel) SendEphemeral added in v0.1.1

func (c *TextChannel) SendEphemeral(receiverIDs []string, content Content, opts *SendOptions) (*api.ChannelMessage, error)

SendEphemeral sends an ephemeral message to the given receivers, port of TextChannel.sendEphemeral (without the reply-reference lookup).

type TransportKind added in v0.2.2

type TransportKind string

TransportKind selects the wire transport used by DefaultSocket.

const (
	// TransportTCP is the raw TLS/TCP transport with MTProto-style "abridged"
	// framing, port of MezonNetworkTcpTransporter (.NET) and MezonNetworkAdapter
	// (mezon-js-protobuf). This is the default.
	TransportTCP TransportKind = "tcp"
	// TransportWebSocket is the protobuf-over-WebSocket transport, port of
	// WebSocketAdapterPb in the TS SDK.
	TransportWebSocket TransportKind = "websocket"
)

type TypeMessage added in v0.1.1

type TypeMessage int

TypeMessage mirrors src/constants/enum.ts TypeMessage (the message "code").

const (
	TypeMessageChat               TypeMessage = 0
	TypeMessageChatUpdate         TypeMessage = 1
	TypeMessageChatRemove         TypeMessage = 2
	TypeMessageTyping             TypeMessage = 3
	TypeMessageIndicator          TypeMessage = 4
	TypeMessageWelcome            TypeMessage = 5
	TypeMessageCreateThread       TypeMessage = 6
	TypeMessageCreatePin          TypeMessage = 7
	TypeMessageMessageBuzz        TypeMessage = 8
	TypeMessageTopic              TypeMessage = 9
	TypeMessageAuditLog           TypeMessage = 10
	TypeMessageSendToken          TypeMessage = 11
	TypeMessageEphemeral          TypeMessage = 12
	TypeMessageUpcomingEvent      TypeMessage = 13
	TypeMessageUpdateEphemeralMsg TypeMessage = 14
	TypeMessageDeleteEphemeralMsg TypeMessage = 15
	TypeMessageContact            TypeMessage = 16
	TypeMessageLocation           TypeMessage = 17
	TypeMessagePoll               TypeMessage = 18
)

type UpdateMessageData added in v0.1.1

type UpdateMessageData struct {
	ClanID            string
	ChannelID         string
	ChannelType       int
	Mode              int
	IsPublic          bool
	MessageID         string
	Content           Content
	Mentions          []Mention
	Attachments       []Attachment
	CreateTimeSeconds uint32
	HideEditted       bool
	TopicID           string
	IsUpdateMsgTopic  bool
}

UpdateMessageData is the payload for editing a message.

type User added in v0.1.1

type User struct {
	ID          string
	Username    string
	ClanNick    string
	ClanAvatar  string
	DisplayName string
	Avatar      string
	DmChannelID string
	// contains filtered or unexported fields
}

User is a Mezon user with DM capability, port of src/mezon-client/structures/User.ts.

func (*User) SendDM added in v0.1.1

func (u *User) SendDM(content Content, code int, attachments []Attachment) (*Message, error)

SendDM sends a direct message to the user, port of User.sendDM. code is the message TypeMessage code (use 0 for a normal chat message). It returns the created Message built from the send ack.

Directories

Path Synopsis
cmd
chantest command
Command chantest is a live probe: it creates a channel in a clan, verifies it exists, deletes it, and verifies it is gone.
Command chantest is a live probe: it creates a channel in a clan, verifies it exists, deletes it, and verifies it is gone.
logintest command
Command logintest checks whether the high-level client.Login() path works for the bot (it used to 403 on ListClanDescs during connectSocket), then exercises Clan.CreateChannel/DeleteChannel through the high-level API.
Command logintest checks whether the high-level client.Login() path works for the bot (it used to 403 on ListClanDescs during connectSocket), then exercises Clan.CreateChannel/DeleteChannel through the high-level API.
replytest command
Command replytest is a live probe for sending/replying into a PRIVATE channel over the default abridged-TCP transport.
Command replytest is a live probe for sending/replying into a PRIVATE channel over the default abridged-TCP transport.
Command example is a minimal Mezon bot using the Go SDK.
Command example is a minimal Mezon bot using the Go SDK.
messagedb module
redisstore module

Jump to

Keyboard shortcuts

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