// Package chat is the public HTTP client for OscarKilo's chat
// service. It is used by `okg` and any other tool that talks
// to oscarkilo.com over the network.
//
// The struct here is named HTTPClient (not just Client) so
// applications can wrap it in their own Client abstractions
// without name collision.
package chat
import "time"
import "oscarkilo.com/okg/internal/rest"
// HTTPClient talks to a //chat server over HTTPS. Embeds the
// shared rest helpers; chat-specific methods live below.
type HTTPClient struct {
*rest.Client
}
func NewHTTPClient(host, apiKey string) *HTTPClient {
return &HTTPClient{Client: rest.NewClient(host, apiKey)}
}
// Message is a single chat message. No JSON tags — the server
// marshals with default Go field names (PascalCase). FUTURE:
// switch to snake_case once the server adds JSON tags.
type Message struct {
From string
To string
Text string
CreatedAt time.Time
}
// SendRequest is the body for POST /chat/send.
type SendRequest struct {
To string `json:"to"`
Text string `json:"text"`
}
// Send posts a message to a //chat group. The caller must have
// post rights on chat://<to>#post.
func (c *HTTPClient) Send(req SendRequest) (*Message, error) {
var msg Message
if err := c.PostJSON("/chat/send", req, &msg); err != nil {
return nil, err
}
return &msg, nil
}
// SetPermissionsRequest is the body for POST
// /chat/permissions/set. Group is the //who username naming the
// channel; Permission ∈ {read, post, join, pin, ban}; Owner
// and Reader are //who usernames (or "" for "anyone" — only
// honored where the backend allows it).
type SetPermissionsRequest struct {
Group string `json:"group"`
Permission string `json:"permission"`
Owner string `json:"owner"`
Reader string `json:"reader"`
}
// SetPermissions writes a //chat authz entry on
// chat://<group>#<permission>.
func (c *HTTPClient) SetPermissions(
req SetPermissionsRequest,
) error {
return c.PostJSON("/chat/permissions/set", req, nil)
}
// SearchRequest is the body for POST /chat/search.
type SearchRequest struct {
To string `json:"to,omitempty"`
}
// SearchResponse is the body of POST /chat/search's response.
type SearchResponse struct {
Messages []*Message `json:"messages"`
}
// Search returns messages matching the filter. The caller must
// have read rights on chat://<To>#read (otherwise the result
// is empty, not an error — per //chat's policy).
func (c *HTTPClient) Search(
req SearchRequest,
) ([]*Message, error) {
var res SearchResponse
if err := c.PostJSON(
"/chat/search", req, &res); err != nil {
return nil, err
}
return res.Messages, nil
}