42c7b8b927
Config gains an intake flag, off by default, and sendMessageReq gains the inline keyboard the intake half hangs under a reply. The gesture itself is the web's, ported: one button says the turn was wrong, and it opens the seven intents rather than writing the negative straight away, because the target is worth much more and he must still be able to decline naming one. Button data comes off the wire, so parseCallback refuses an id it cannot parse and a target that is not one of the seven. A label nothing can score is worse than no label.
102 lines
3.2 KiB
Go
102 lines
3.2 KiB
Go
// correction.go — the correction gesture as it appears in the chat (V-637).
|
|
// Two taps at most: "не то" opens the seven intents, and one of them writes the
|
|
// label. The web's version of the same gesture is cmd/mavweb/chat.go.
|
|
package telegramsink
|
|
|
|
import (
|
|
"fmt"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
// CorrectionTargets — the intents a correction may name, in the order the
|
|
// buttons are drawn. It mirrors the seven the web offers, and it is a closed
|
|
// list for the same reason: V-632 fits prototypes from the label table, and a
|
|
// label nothing can score is worse than no label.
|
|
var CorrectionTargets = []string{"fact", "note", "reminder", "query", "act", "chat", "system"}
|
|
|
|
// correctionKeyboard — the one gesture beside the reply. Nothing when the turn
|
|
// did not persist: a button that cannot name a row would report a failure the
|
|
// owner cannot act on.
|
|
func (p *Poller) correctionKeyboard(traceID int64) *inlineKeyboard {
|
|
if traceID <= 0 || p.correct == nil {
|
|
return nil
|
|
}
|
|
return &inlineKeyboard{Rows: [][]inlineButton{{
|
|
{Text: "не то", Data: fmt.Sprintf("%s%d", prefixAsk, traceID)},
|
|
}}}
|
|
}
|
|
|
|
// targetKeyboard — the seven intents, plus the cheap half kept reachable. He
|
|
// opened the row without knowing he had to name something, and closing it with
|
|
// no way out would price the negative he was willing to give.
|
|
func targetKeyboard(traceID int64) *inlineKeyboard {
|
|
var rows [][]inlineButton
|
|
row := []inlineButton{}
|
|
for _, t := range CorrectionTargets {
|
|
row = append(row, inlineButton{Text: t, Data: fmt.Sprintf("%s%d:%s", prefixTarget, traceID, t)})
|
|
if len(row) == 4 {
|
|
rows, row = append(rows, row), nil
|
|
}
|
|
}
|
|
if len(row) > 0 {
|
|
rows = append(rows, row)
|
|
}
|
|
return &inlineKeyboard{Rows: append(rows, []inlineButton{
|
|
{Text: "просто неверно", Data: fmt.Sprintf("%s%d:", prefixTarget, traceID)},
|
|
})}
|
|
}
|
|
|
|
// Callback data is capped at 64 bytes by telegram, so it carries the trace id
|
|
// and the target and nothing else.
|
|
const (
|
|
prefixAsk = "w:"
|
|
prefixTarget = "t:"
|
|
)
|
|
|
|
type callbackKind int
|
|
|
|
const (
|
|
callbackUnknown callbackKind = iota
|
|
callbackAskTarget
|
|
callbackTarget
|
|
)
|
|
|
|
// parseCallback reads button data. An unparseable id, or a target that is not
|
|
// one of the seven, is callbackUnknown — the data came off the wire, and a
|
|
// label the fitting code cannot score is worse than no label.
|
|
func parseCallback(data string) (traceID int64, target string, kind callbackKind) {
|
|
switch {
|
|
case strings.HasPrefix(data, prefixAsk):
|
|
id, err := strconv.ParseInt(strings.TrimPrefix(data, prefixAsk), 10, 64)
|
|
if err != nil || id <= 0 {
|
|
return 0, "", callbackUnknown
|
|
}
|
|
return id, "", callbackAskTarget
|
|
case strings.HasPrefix(data, prefixTarget):
|
|
rest := strings.TrimPrefix(data, prefixTarget)
|
|
idPart, target, ok := strings.Cut(rest, ":")
|
|
if !ok {
|
|
return 0, "", callbackUnknown
|
|
}
|
|
id, err := strconv.ParseInt(idPart, 10, 64)
|
|
if err != nil || id <= 0 {
|
|
return 0, "", callbackUnknown
|
|
}
|
|
if target != "" && !isCorrectionTarget(target) {
|
|
return 0, "", callbackUnknown
|
|
}
|
|
return id, target, callbackTarget
|
|
}
|
|
return 0, "", callbackUnknown
|
|
}
|
|
|
|
func isCorrectionTarget(s string) bool {
|
|
for _, t := range CorrectionTargets {
|
|
if t == s {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|