Skip to content
quarry Artifact [3bcc265c5f]
Login

Artifact [3bcc265c5f]

Artifact 3bcc265c5fe1d0aece77f3f280a82affe553c1e8fa0dd9b43495bc12c8f17c8f:


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)
	}
}