When golem15.chat is active, Boot registers the context alias bm (id 1) on its registry. Membership is the user group jz.bm.chat.group (default studenci); CanOverseeChats is always false, so nobody reads other people's DMs or edits their messages; the broadcast channel is chat:context:1, never empty. GET /_bm/api/v1/chat answers the caller's membership behind jwt.auth and the per-user bucket jz.bm.chat (240 a minute). The chat config block (group, moderator_group, max_upload_bytes, max_embeds) is added. jz.bm still Requires only golem15.user; all chat wiring is gated by HasPlugin.
91 lines
2.8 KiB
Go
91 lines
2.8 KiB
Go
package bm
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
|
|
chatcontracts "git.golem15.com/golem15/sm-chat-plugin/contracts"
|
|
"git.golem15.com/golem15/summercms/modules/backpack"
|
|
"git.golem15.com/jakub/sm-bm-plugin/classes"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
// The chat config keys and their fallbacks (config/config.yaml).
|
|
const (
|
|
configChatGroup = "jz.bm.chat.group"
|
|
configChatModeratorGroup = "jz.bm.chat.moderator_group"
|
|
configChatMaxUpload = "jz.bm.chat.max_upload_bytes"
|
|
configChatMaxEmbeds = "jz.bm.chat.max_embeds"
|
|
|
|
defaultChatGroup = "studenci"
|
|
defaultChatModeratorGroup = "moderatorzy"
|
|
defaultChatMaxUpload = 62914560
|
|
defaultChatMaxEmbeds = 3
|
|
)
|
|
|
|
// registerChat makes jz.bm the host of the BM chat: it registers the bm
|
|
// context alias on golem15.chat's registry. Without golem15.chat it does
|
|
// nothing, so jz.bm keeps working (and its tests keep activating) without
|
|
// the chat plugins; jz.bm does not Require them.
|
|
func (p *Plugin) registerChat(app *backpack.App) error {
|
|
if app == nil || !app.HasPlugin("golem15.chat") {
|
|
return nil
|
|
}
|
|
reg, ok := app.Lookup[*chatcontracts.Registry]()
|
|
if !ok || reg == nil {
|
|
return errors.New("jz.bm: golem15.chat must be listed before jz.bm in summer.yaml")
|
|
}
|
|
return reg.Add(p.ID(), chatcontracts.Registration{Alias: classes.ChatContextType, Loader: p.loadChatContext})
|
|
}
|
|
|
|
// loadChatContext is the loader of the bm alias. The only context is id 1;
|
|
// any other id is unknown, which golem15.chat answers with its not-a-member
|
|
// error.
|
|
func (p *Plugin) loadChatContext(_ context.Context, db *gorm.DB, id uint) (chatcontracts.Context, error) {
|
|
if id != classes.ChatContextID {
|
|
return nil, nil
|
|
}
|
|
return classes.NewChatContext(db, p.chatGroup(), p.chatModeratorGroup()), nil
|
|
}
|
|
|
|
// chatGroup is the code of the user group whose members are in the chat.
|
|
func (p *Plugin) chatGroup() string {
|
|
return p.configString(configChatGroup, defaultChatGroup)
|
|
}
|
|
|
|
// chatModeratorGroup is the code of the user group whose members moderate
|
|
// the chat's channels.
|
|
func (p *Plugin) chatModeratorGroup() string {
|
|
return p.configString(configChatModeratorGroup, defaultChatModeratorGroup)
|
|
}
|
|
|
|
// chatMaxUploadBytes is the total attachment size of one message.
|
|
func (p *Plugin) chatMaxUploadBytes() int {
|
|
return p.configInt(configChatMaxUpload, defaultChatMaxUpload)
|
|
}
|
|
|
|
// chatMaxEmbeds is the number of entity embeds one message may carry.
|
|
func (p *Plugin) chatMaxEmbeds() int {
|
|
return p.configInt(configChatMaxEmbeds, defaultChatMaxEmbeds)
|
|
}
|
|
|
|
func (p *Plugin) configString(key, fallback string) string {
|
|
if p.app == nil || p.app.Config == nil {
|
|
return fallback
|
|
}
|
|
if v := p.app.Config.String(key); v != "" {
|
|
return v
|
|
}
|
|
return fallback
|
|
}
|
|
|
|
func (p *Plugin) configInt(key string, fallback int) int {
|
|
if p.app == nil || p.app.Config == nil {
|
|
return fallback
|
|
}
|
|
if v := p.app.Config.Int(key); v > 0 {
|
|
return v
|
|
}
|
|
return fallback
|
|
}
|