osmose

package module
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Sep 1, 2026 License: MIT Imports: 3 Imported by: 0

README

docshelf logo

Osmose

A fast and idiomatic Go SDK for building bots on the Osmium protocol.


CI Latest release License Go Reference


Why Osmose?

Osmose is a small, typed Go SDK for creating bots on the Osmium protocol.

The SDK hides WebSocket frames, binary Protocol Buffers, request correlation, keepalive, reconnect, and shutdown behind a straightforward client API. The generated protocol packages remain available for advanced integrations.

Read the Osmose documentation for the complete guide.

Installation

Add Osmose to a Go module:

go get github.com/ofabiodev/osmose

Generated protocol packages are included, so installing Osmose does not require protoc.

Development checkout

Clone the repository with its pinned Osmium protocol schema:

git clone --recurse-submodules https://github.com/ofabiodev/osmose.git
cd osmose

If the repository was cloned without submodules, initialize the schema with:

git submodule update --init --recursive

The schema submodule is used to regenerate protocol code. The generated Go packages are committed to this repository, so installing Osmose does not require the protobuf toolchain.

Transparency
Transparency is a core pillar of my projects. AI is used as a supporting tool where it helps, mainly for code completion and translating technical documentation. The architecture, decisions, review, testing, and responsibility for the released code remain with the project owner.

Feature Coverage

Legend:

Status Meaning
Fully implemented and stable
🟡 Partially implemented / missing important features
🟠 Available through Raw API but not wrapped yet
Not implemented yet / planned
Area Status Details
Client Central client, configuration, lifecycle, typed services
Gateway Binary protobuf WebSocket, keepalive, reconnect handling
Lifecycle Connect, initialize, authorize, ready, reconnect, shutdown
RPC Request correlation, context cancellation, timeouts, typed errors
Events 🟡 Typed events for core bot operations. Some protocol updates require Raw access
Collectors Message, interaction, and reaction collectors with filters and time limits
Messages 🟡 Service and rich-object message operations. High-level media upload/download is still missing
Chats 🟡 Fetching and members support. Chat management operations are not wrapped yet
Communities 🟡 Rich community, channel, member, and role operations. Settings and channel overrides remain
Users User fetching and profile access
Reactions Add and remove reactions
Voice Voice room control-plane operations
Media 🟠 Protocol support exists. High-level upload/download API is not available yet
Interactions 🟡 Basic interaction events and responses. Advanced components are missing
Models Rich Community, Channel, Message, Member, and Role objects with Raw escape hatches
Cache No built-in cache system
Managers No object managers yet
Permissions 🟡 Role and default-permission operations are wrapped; channel overrides remain available through Raw
Builders Message and component builders are planned
Raw API Full protobuf escape hatch for unsupported operations
Safety Bounded queues, cancellation, reconnect backoff, concurrency safety
Documentation Public docs and examples

Quick start

package main

import (
	"context"
	"log"
	"os"
	"os/signal"

	"github.com/ofabiodev/osmose"
)

func main() {
	ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt)
	defer stop()

	client, err := osmose.New(osmose.Config{
		Token:    os.Getenv("OSMIUM_TOKEN"),
		ClientID: 123456,
	})
	if err != nil {
		log.Fatal(err)
	}

	client.OnReady(func(_ context.Context, event *osmose.ReadyEvent) error {
		log.Printf("connected as %s", event.User.Username)
		return nil
	})

	client.OnMessageCreate(func(ctx context.Context, event *osmose.MessageCreateEvent) error {
		if event.Message.Content != "!ping" {
			return nil
		}
		return event.Reply(ctx, "Pong! 🏓")
	})

	if err := client.Run(ctx); err != nil {
		log.Fatal(err)
	}
}

Set the token before running the bot:

export OSMIUM_TOKEN="your-bot-token"
go run .

On PowerShell:

$env:OSMIUM_TOKEN = "your-bot-token"
go run .

Run manages the connection, handshake, event dispatch, keepalive, reconnect, and shutdown for the client.

Events

Handlers are strongly typed, return an error, and can be removed:

remove := client.OnMessageUpdate(func(_ context.Context, event *osmose.MessageUpdateEvent) error {
	log.Printf("message %d changed", event.Message.ID)
	return nil
})
defer remove()

client.OnInteraction(func(ctx context.Context, event *osmose.InteractionEvent) error {
	if event.Data == "confirm" {
		return event.Reply(ctx, "Confirmed")
	}
	return event.Defer(ctx)
})

Typed events include connection lifecycle, ready, message, channel, user, community, typing, member, reaction, read-marker, interaction, and voice room updates. Use OnUpdate when an application needs the raw generated update.

Event delivery is bounded, so a slow handler cannot create an unlimited number of goroutines. Set EventWorkers above one when handlers may run concurrently. DroppedEvents and OnEventOverflow make queue drops observable.

Collectors

Collectors are useful for confirmations, forms, and multi-step conversations:

event, err := client.AwaitMessage(ctx, osmose.MessageCollectorOptions{
	Chat:     chat,
	AuthorID: userID,
	Time:     time.Minute,
})
if err != nil {
	return err
}

return event.Reply(ctx, "Recebi: "+event.Message.Content)

Use CollectMessages when more than one matching message is needed. Message, interaction, and reaction collectors support typed filters, maximum counts, idle timeouts, total timeouts, cancellation, and bounded buffers.

See the collector guide for a complete form flow.

Sending messages

Use parameter structs instead of constructing protobuf requests:

import (
	"github.com/ofabiodev/osmose/messages"
	"github.com/ofabiodev/osmose/types"
)

sent, err := client.Messages.Send(ctx, messages.SendParams{
	Chat:    types.SelfChat(),
	Content: "Choose an action:",
})
if err != nil {
	return err
}

log.Printf("sent message %d", sent.ID)

Replying to a message event is shorter:

return event.Reply(ctx, "Pong!")

Common chat references are types.SelfChat(), types.UserChat(id), types.GroupChat(id), and types.ChannelChat(communityID, channelID).

Rich objects

Models returned by the community, chat, message, and event APIs keep a private reference to the client, so common operations can be written directly on the object:

communities, err := client.Communities.List(ctx)
if err != nil {
	return err
}

channels, err := communities.Communities[0].Channels(ctx)
if err != nil {
	return err
}

message, err := channels[0].Send(ctx, types.MessageSendParams{Content: "Hello"})
if err != nil {
	return err
}

return message.Pin(ctx)

Rich Community, Channel, Message, Member, and Role objects cover common reads and mutations while keeping Raw available for protocol features that are not wrapped yet. See the rich object guide.

Reply metadata is available as message.ReplyInfo; message.Reply(ctx, content) is the object operation for sending a reply.

Services

Service Operations
Messages Send, Reply, History, Search, PinnedMessages, UnreadMentions, Edit, Delete
Chats List, Get, Members, SetTyping
Communities List, Channels, ChannelMembers
Users Get, Profile
Reactions Add, Remove
Voice RequestRoom, RoomStates, DisconnectUser

Every network operation accepts context.Context.

Models

The types package contains the public models shared by services and events:

Type Use
types.ID Explicit Osmium identifier type
types.User User identity, status, photo, and bot information
types.Message Message content, author, chat, reply metadata, media, entities, and bot info
types.ChatRef Self, user, group, or community channel reference
types.Conversation Chat state and read markers
types.Group, types.Channel, types.Community Conversation and community information
types.CommunityMember, types.CommunityRole Community membership, roles, and permissions
types.ChatMember Chat membership and permissions
types.Emoji Unicode or custom reaction emoji
types.MemberListEntry, types.MemberListDivider Ordered community-channel member list entries
types.Interaction Interaction IDs and action data

Models expose useful fields directly. Where it is useful for advanced code, the original generated value remains available through Raw.

Errors

Use errors.Is and errors.As instead of matching error strings:

if errors.Is(err, osmose.ErrPermanent) {
	log.Fatal("the server rejected the connection permanently")
}

var rpcErr *osmose.RPCError
if errors.As(err, &rpcErr) {
	log.Printf("RPC %d: %s", rpcErr.Code, rpcErr.Message)
}

Osmose exposes typed errors for closed clients, connection state, permanent authorization failures, protocol mismatches, RPC failures, and collector termination reasons.

Configuration

Only Token and ClientID are required:

client, err := osmose.New(osmose.Config{
	Token:    token,
	ClientID: clientID,
})

Optional settings include:

Setting Purpose
ServerURL Use a different Osmium WebSocket endpoint
Logger Configure log/slog output
RequestTimeout Set the default RPC timeout
RequestInterval Add a minimum interval between outbound requests
HeartbeatInterval Configure the session keepalive interval
EventQueue, EventWorkers Control bounded event delivery
OnHandlerError, OnEventOverflow Observe handler failures and dropped events
WriteQueue, WriteTimeout Control outbound backpressure
BackoffMin, BackoffMax Bound reconnect delays

Zero values use sensible defaults.

Advanced / raw API

When a service does not cover an endpoint, use a generated protocol request:

import protoCommunities "github.com/ofabiodev/osmose/proto/communities"

result, err := client.Raw().Call(ctx, &protoCommunities.GetCommunities{})
if err != nil {
	return err
}

communities := result.GetCommunities()

The generated protocol packages are included in the module and the raw API is kept separate from the common service API.

Protocol

Osmose follows Osmium's RPC-over-WebSocket protocol:

WebSocket
  → binary protobuf ServerMessage
  → RPC result → waiting request
  → update → typed event handler

The connection handshake is:

Connect → Initialize → Initialized → Authorize → Authorization → Ready

Connection failures are retried with bounded backoff. Pending requests are completed when a connection ends, and reconnect performs the handshake again. Osmose uses the current Osmium protocol rather than adding a REST layer.

Documentation

The complete documentation is published at ofabiodev.github.io/osmose.

To preview the documentation locally:

cd docs
bun install
bun run docs:dev

See CONTRIBUTING.md for contribution and development instructions.

License

MIT © ofabiodev

Documentation

Overview

Package osmose is the idiomatic Go SDK for Osmium bots.

Osmose hides the WebSocket, binary protobuf, handshake, reconnect, and RPC correlation details behind a small typed client API. Advanced users can use Client.Raw to send generated protobuf requests directly.

Index

Constants

View Source
const (
	Disconnected   = coreclient.Disconnected
	Connecting     = coreclient.Connecting
	Initializing   = coreclient.Initializing
	Authenticating = coreclient.Authenticating
	Ready          = coreclient.Ready
	Closing        = coreclient.Closing
)
View Source
const (
	EndReasonTime     = collectors.EndReasonTime
	EndReasonIdle     = collectors.EndReasonIdle
	EndReasonLimit    = collectors.EndReasonLimit
	EndReasonStopped  = collectors.EndReasonStopped
	EndReasonContext  = collectors.EndReasonContext
	EndReasonOverflow = collectors.EndReasonOverflow
	EndReasonClosed   = collectors.EndReasonClosed
)

Variables

View Source
var (
	ErrClosed              = coreclient.ErrClosed
	ErrNotConnected        = coreclient.ErrNotConnected
	ErrNotReady            = coreclient.ErrNotReady
	ErrAlreadyRunning      = coreclient.ErrAlreadyRunning
	ErrRunCompleted        = coreclient.ErrRunCompleted
	ErrPermanent           = coreclient.ErrPermanent
	ErrAuthorizationFailed = coreclient.ErrAuthorizationFailed
	ErrProtocolMismatch    = coreclient.ErrProtocolMismatch
	ErrDisconnected        = coreclient.ErrDisconnected
	ErrUnsupportedRequest  = coreclient.ErrUnsupportedRequest
	ErrEventQueueFull      = events.ErrEventQueueFull
	ErrCollectorEnded      = collectors.ErrCollectorEnded
	ErrCollectorTimeout    = collectors.ErrCollectorTimeout
	ErrCollectorIdle       = collectors.ErrCollectorIdle
	ErrCollectorOverflow   = collectors.ErrCollectorOverflow
	ErrCollectorClosed     = collectors.ErrCollectorClosed
)

Functions

func IsPermanent

func IsPermanent(err error) bool

Types

type ChannelDeleteEvent

type ChannelDeleteEvent = events.ChannelDeleteEvent

type ChannelDeleteHandler

type ChannelDeleteHandler = events.ChannelDeleteHandler

type ChannelUpdateEvent

type ChannelUpdateEvent = events.ChannelUpdateEvent

type ChannelUpdateHandler

type ChannelUpdateHandler = events.ChannelUpdateHandler

type ChatTypingEvent

type ChatTypingEvent = events.ChatTypingEvent

type ChatTypingHandler

type ChatTypingHandler = events.ChatTypingHandler

type Client

type Client = coreclient.Client

func New

func New(config Config) (*Client, error)

type CollectorError

type CollectorError = collectors.CollectorError

type CollectorResult

type CollectorResult = collectors.CollectorResult

type CommunityDeleteEvent

type CommunityDeleteEvent = events.CommunityDeleteEvent

type CommunityDeleteHandler

type CommunityDeleteHandler = events.CommunityDeleteHandler

type CommunityUpdateEvent

type CommunityUpdateEvent = events.CommunityUpdateEvent

type CommunityUpdateHandler

type CommunityUpdateHandler = events.CommunityUpdateHandler

type Config

type Config = coreclient.Config

type ConnectionEvent

type ConnectionEvent = events.ConnectionEvent

type ConnectionHandler

type ConnectionHandler = events.ConnectionHandler

type ConversationLastReadEvent

type ConversationLastReadEvent = events.ConversationLastReadEvent

type ConversationLastReadHandler

type ConversationLastReadHandler = events.ConversationLastReadHandler

type EndReason

type EndReason = collectors.EndReason

type EventOverflowHandler

type EventOverflowHandler = events.EventOverflowHandler

type HandlerError

type HandlerError = events.HandlerError

type HandlerErrorHandler

type HandlerErrorHandler = events.HandlerErrorHandler

type InteractionCollector

type InteractionCollector = collectors.InteractionCollector

type InteractionCollectorOptions

type InteractionCollectorOptions = collectors.InteractionCollectorOptions

type InteractionEvent

type InteractionEvent = events.InteractionEvent

type InteractionHandler

type InteractionHandler = events.InteractionHandler

type MemberCreateEvent

type MemberCreateEvent = events.MemberCreateEvent

type MemberCreateHandler

type MemberCreateHandler = events.MemberCreateHandler

type MemberDeleteEvent

type MemberDeleteEvent = events.MemberDeleteEvent

type MemberDeleteHandler

type MemberDeleteHandler = events.MemberDeleteHandler

type MemberUpdateEvent

type MemberUpdateEvent = events.MemberUpdateEvent

type MemberUpdateHandler

type MemberUpdateHandler = events.MemberUpdateHandler

type MessageCollector

type MessageCollector = collectors.MessageCollector

type MessageCollectorOptions

type MessageCollectorOptions = collectors.MessageCollectorOptions

type MessageCreateEvent

type MessageCreateEvent = events.MessageCreateEvent

type MessageCreateHandler

type MessageCreateHandler = events.MessageCreateHandler

type MessageDeleteEvent

type MessageDeleteEvent = events.MessageDeleteEvent

type MessageDeleteHandler

type MessageDeleteHandler = events.MessageDeleteHandler

type MessageReactionsEvent

type MessageReactionsEvent = events.MessageReactionsEvent

type MessageReactionsHandler

type MessageReactionsHandler = events.MessageReactionsHandler

type MessageUpdateEvent

type MessageUpdateEvent = events.MessageUpdateEvent

type MessageUpdateHandler

type MessageUpdateHandler = events.MessageUpdateHandler

type PermanentError

type PermanentError = coreclient.PermanentError

type RPCError

type RPCError = coreclient.RPCError

type RawClient

type RawClient = coreclient.RawClient

type ReactionCollector

type ReactionCollector = collectors.ReactionCollector

type ReactionCollectorOptions

type ReactionCollectorOptions = collectors.ReactionCollectorOptions

type ReadyEvent

type ReadyEvent = events.ReadyEvent

type ReadyHandler

type ReadyHandler = events.ReadyHandler

type State

type State = coreclient.State

type UnexpectedResultError

type UnexpectedResultError = coreclient.UnexpectedResultError

type UpdateEvent

type UpdateEvent = events.UpdateEvent

type UpdateHandler

type UpdateHandler = events.UpdateHandler

type UserUpdateEvent

type UserUpdateEvent = events.UserUpdateEvent

type UserUpdateHandler

type UserUpdateHandler = events.UserUpdateHandler

type VoiceRoomParticipantEvent

type VoiceRoomParticipantEvent = events.VoiceRoomParticipantEvent

type VoiceRoomParticipantHandler

type VoiceRoomParticipantHandler = events.VoiceRoomParticipantHandler

type VoiceRoomStateEvent

type VoiceRoomStateEvent = events.VoiceRoomStateEvent

type VoiceRoomStateHandler

type VoiceRoomStateHandler = events.VoiceRoomStateHandler

Directories

Path Synopsis
Package collectors provides bounded helpers for waiting on typed events.
Package collectors provides bounded helpers for waiting on typed events.
Package events contains the typed event payloads emitted by Osmose.
Package events contains the typed event payloads emitted by Osmose.
examples
basic command
ping command
internal
client
Package client contains the internal implementation behind the public osmose package.
Package client contains the internal implementation behind the public osmose package.
gateway
Package gateway owns the single WebSocket reader and controlled writer used by an Osmium client.
Package gateway owns the single WebSocket reader and controlled writer used by an Osmium client.
rpc
proto
tools
protogen command
wrapgen command
Package types contains the small public models shared by Osmose services and events.
Package types contains the small public models shared by Osmose services and events.
Package voice exposes the voice control-plane operations present in the Osmium protocol.
Package voice exposes the voice control-plane operations present in the Osmium protocol.

Jump to

Keyboard shortcuts

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