package web
import (
"context"
"net/url"
"strings"
"craftdesign.group/quarry/internal/ops"
)
// chatNotifyChoice is one thing a reader can hear from a chat channel,
// as the channel header's bell offers it (api/chatnotify.go).
type chatNotifyChoice struct {
Mode string // the op's word: mentions, all, off
Label string // the menu's line
Says string // what it means, under the line
Word string // the bell's own word for it when chosen
}
// chatNotifyChoices are the bell's menu, in order.
var chatNotifyChoices = []chatNotifyChoice{
{"mentions", "Mentions", "Only messages that name you", "Mentions"},
{"all", "Every message", "Everything here, as an email digest at most every 30 minutes", "All"},
{"off", "Off", "Nothing from this channel, not even mentions", "Off"},
}
// chatNotifyWord is the bell's word for mode.
func chatNotifyWord(mode string) string {
for _, c := range chatNotifyChoices {
if c.Mode == mode {
return c.Word
}
}
return "Mentions"
}
// chatAs resolves a channel's bridged names (fossil:<login>) to the
// accounts they are linked to (api chat.identities), so a row shows the
// person rather than the upstream login. A repository's links are asked
// for once per page or stream, the first time one of its bridged names
// is drawn; a channel with no bridge never asks.
type chatAs struct {
ctx context.Context
r *ops.Registry
links map[string]map[string]string // repo -> remote -> account
}
func newChatAs(ctx context.Context, r *ops.Registry) *chatAs {
return &chatAs{ctx: ctx, r: r, links: map[string]map[string]string{}}
}
// of is the account user is linked to in repo's channel, or "".
func (c *chatAs) of(repo, user string) string {
if c == nil || repo == "" || !strings.HasPrefix(user, "fossil:") {
return ""
}
l, ok := c.links[repo]
if !ok {
l = map[string]string{}
if out, err := invoke(c.ctx, c.r, "chat.identities", url.Values{"repo": {repo}}); err == nil {
var v struct {
Links []struct {
Remote string `json:"remote"`
Account string `json:"account"`
} `json:"links"`
}
remarshal(out, &v)
for _, k := range v.Links {
l[k.Remote] = k.Account
}
}
c.links[repo] = l
}
return l[user]
}
// apply sets As on every message of repo's channel (or of the channel a
// merged room's line names).
func (c *chatAs) apply(repo string, msgs []ChatMessage) {
for i := range msgs {
in := msgs[i].Repo
if in == "" {
in = repo
}
msgs[i].As = c.of(in, msgs[i].User)
}
}