Documentation
¶
Index ¶
- Constants
- func CookieFilePath() (string, error)
- func LoadCookie() (string, error)
- func LoginWithBrowser(ctx context.Context, timeout time.Duration) (string, error)
- func SaveCookie(cookie string) error
- func StorageDir(channelID string) (string, error)
- type APIError
- type Channel
- type Client
- func (c *Client) BaseURL() string
- func (c *Client) GetChannelPosts(ctx context.Context, channelID string, q PostsQuery) (*PostList, error)
- func (c *Client) GetMe(ctx context.Context) (*User, error)
- func (c *Client) GetMyTeams(ctx context.Context) ([]Team, error)
- func (c *Client) GetTeamByName(ctx context.Context, name string) (*Team, error)
- func (c *Client) GetUserByUsername(ctx context.Context, username string) (*User, error)
- func (c *Client) GetUserChannelsForTeam(ctx context.Context, userID, teamID string) ([]Channel, error)
- func (c *Client) ResolveBotChannel(ctx context.Context, teamName, botUsername string) (*User, *User, *Channel, error)
- func (c *Client) Token() string
- func (c *Client) ValidateToken(ctx context.Context) error
- type Config
- type NotificationsSource
- type Post
- type PostList
- type PostsQuery
- type State
- type Store
- type StoreSource
- type Team
- type User
Constants ¶
const ( APIPrefix = "/api/v4" DefaultTimeout = 30 * time.Second MeEndpoint = APIPrefix + "/users/me" MyTeamsEndpoint = APIPrefix + "/users/me/teams" TeamByNameEndpoint = APIPrefix + "/teams/name/%s" UserChannelsEndpoint = APIPrefix + "/users/%s/teams/%s/channels" UserByUsernameEndpoint = APIPrefix + "/users/username/%s" ChannelPostsEndpoint = APIPrefix + "/channels/%s/posts" )
const ( DefaultBaseURL = "https://time.cu.ru" DefaultTeamName = "tsentralnyy-universitet" DefaultBotUsername = "cu_notification_bot" CookieName = "MMAUTHTOKEN" EnvBaseURL = "CU_MM_BASE_URL" EnvTeamName = "CU_MM_TEAM" EnvBotUsername = "CU_MM_BOT_USERNAME" EnvToken = "CU_MM_TOKEN" // #nosec G101 -- env var name, not a credential )
Defaults for the Mattermost instance run by Central University. Override via environment variables if the deployment changes.
Variables ¶
This section is empty.
Functions ¶
func CookieFilePath ¶
func LoadCookie ¶
func LoginWithBrowser ¶
LoginWithBrowser opens Chrome for Mattermost SSO login and captures MMAUTHTOKEN.
func SaveCookie ¶
func StorageDir ¶
StorageDir returns the per-channel directory under ~/.cu-cli/mm/<channelID>.
Types ¶
type APIError ¶
type APIError struct {
ID string `json:"id"`
Message string `json:"message"`
DetailedError string `json:"detailed_error"`
StatusCode int `json:"status_code"`
}
APIError mirrors the Mattermost error envelope.
type Channel ¶
type Channel struct {
ID string `json:"id"`
TeamID string `json:"team_id"`
Type string `json:"type"` // "O" public, "P" private, "D" direct, "G" group
Name string `json:"name"`
DisplayName string `json:"display_name"`
}
Channel represents a Mattermost channel. For direct messages the `name` field has the form "<userID1>__<userID2>" sorted lexicographically.
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
func NewClientFromEnv ¶
NewClientFromEnv loads a token from CU_MM_TOKEN or the saved cookie file and uses CU_MM_BASE_URL when set, otherwise DefaultBaseURL.
func NewClientWithBase ¶
func (*Client) GetChannelPosts ¶
func (c *Client) GetChannelPosts(ctx context.Context, channelID string, q PostsQuery) (*PostList, error)
GetChannelPosts returns a page of posts for a channel.
func (*Client) GetMyTeams ¶
GetMyTeams returns teams the authenticated user belongs to.
func (*Client) GetTeamByName ¶
GetTeamByName looks up a team by its URL slug.
func (*Client) GetUserByUsername ¶
GetUserByUsername resolves a user by their username (without leading '@').
func (*Client) GetUserChannelsForTeam ¶
func (c *Client) GetUserChannelsForTeam(ctx context.Context, userID, teamID string) ([]Channel, error)
GetUserChannelsForTeam returns channels the user is a member of for the given team.
func (*Client) ResolveBotChannel ¶
func (c *Client) ResolveBotChannel( ctx context.Context, teamName, botUsername string, ) (*User, *User, *Channel, error)
ResolveBotChannel finds the direct-message channel between the authenticated user and the bot identified by botUsername within the team teamName. teamName may be empty: the first team the user belongs to is used.
type Config ¶
Config groups the tunable knobs for the Mattermost gateway.
func LoadConfig ¶
func LoadConfig() Config
type NotificationsSource ¶
type NotificationsSource struct {
Store *Store
}
NotificationsSource adapts the JSONL Store to notifications.PostSource.
func NewNotificationsSource ¶
func NewNotificationsSource(s *Store) *NotificationsSource
func (*NotificationsSource) LoadPosts ¶
func (s *NotificationsSource) LoadPosts(_ context.Context) ([]notifications.RawPost, error)
type Post ¶
type Post struct {
ID string `json:"id"`
ChannelID string `json:"channel_id"`
UserID string `json:"user_id"`
RootID string `json:"root_id"`
Type string `json:"type"`
Message string `json:"message"`
CreateAt int64 `json:"create_at"` // unix ms
UpdateAt int64 `json:"update_at"`
DeleteAt int64 `json:"delete_at"`
FileIDs []string `json:"file_ids,omitempty"`
Props map[string]any `json:"props,omitempty"`
Metadata map[string]any `json:"metadata,omitempty"`
}
Post is a chat message.
type PostList ¶
type PostList struct {
Order []string `json:"order"`
Posts map[string]*Post `json:"posts"`
NextPostID string `json:"next_post_id"`
PrevPostID string `json:"prev_post_id"`
}
PostList is the standard Mattermost paginated post response.
type PostsQuery ¶
type PostsQuery struct {
Since int64 // unix ms; if >0 returns posts created/updated since this time
After string // post ID; returns posts after this one
Before string // post ID; returns posts before this one
Page int
PerPage int
}
PostsQuery controls /channels/{id}/posts paging.
type State ¶
type State struct {
ChannelID string `json:"channel_id"`
LastPostID string `json:"last_post_id"`
LastCreateAt int64 `json:"last_create_at"`
SyncedAt int64 `json:"synced_at"`
BotUserID string `json:"bot_user_id,omitempty"`
BotUsername string `json:"bot_username,omitempty"`
}
State persists incremental sync progress for a channel.
type Store ¶
type Store struct {
// contains filtered or unexported fields
}
Store is an append-only JSONL store for posts plus a small JSON state file.
func (*Store) AppendPosts ¶
AppendPosts writes posts as JSONL, ordered by CreateAt ascending. Returns the number of new posts persisted and the latest seen create_at/id.
type StoreSource ¶
type StoreSource struct {
Store *Store
}
StoreSource adapts a local JSONL Store to the recordings.PostSource interface.
func NewStoreSource ¶
func NewStoreSource(s *Store) *StoreSource
func (*StoreSource) LoadPosts ¶
func (s *StoreSource) LoadPosts(_ context.Context) ([]recordings.RawPost, error)
LoadPosts streams every post from the channel JSONL file. limit==0 means "all posts".