Make omemo/preset dropdowns in Ad-Hoc

This commit is contained in:
Bohdan Horbeshko 2026-08-17 13:21:07 -04:00
parent 57a579ddd9
commit afb892d493
3 changed files with 20 additions and 76 deletions

View file

@ -70,7 +70,6 @@ var transportCommands = map[string]command{
"supergroup": command{1, []string{"title", "description"}, "create new supergroup «title» with «description»", true, nil, true}, "supergroup": command{1, []string{"title", "description"}, "create new supergroup «title» with «description»", true, nil, true},
"channel": command{1, []string{"title", "description"}, "create new channel «title» with «description»", true, nil, true}, "channel": command{1, []string{"title", "description"}, "create new channel «title» with «description»", true, nil, true},
"preset": command{1, []string{"modern|classic|pass"}, "apply a config preset", false, nil, false}, "preset": command{1, []string{"modern|classic|pass"}, "apply a config preset", false, nil, false},
"omemo": command{0, []string{"on|auto|off"}, "view or set the account-wide OMEMO encryption mode", false, nil, false},
"pass": command{0, []string{}, "proceed to next login stage", false, nil, false}, "pass": command{0, []string{}, "proceed to next login stage", false, nil, false},
"finish": command{0, []string{}, "skip post-login configuration", false, nil, false}, "finish": command{0, []string{}, "skip post-login configuration", false, nil, false},
} }
@ -128,7 +127,7 @@ var transportConfigurationOptions = map[string]configurationOption{
"receipts": configurationOption{"<bool>", "if enabled, XMPP read receipts are synced to Telegram, otherwise, messages are marked as read automatically (true/false)"}, "receipts": configurationOption{"<bool>", "if enabled, XMPP read receipts are synced to Telegram, otherwise, messages are marked as read automatically (true/false)"},
"nativeedits": configurationOption{"<bool>", "if possible, edit XMPP messages instead of showing Telegram edits as separate messages (true/false)"}, "nativeedits": configurationOption{"<bool>", "if possible, edit XMPP messages instead of showing Telegram edits as separate messages (true/false)"},
"ignoregroupdeletions": configurationOption{"<bool>", "suppress message deletion messages in group chats (true/false)"}, "ignoregroupdeletions": configurationOption{"<bool>", "suppress message deletion messages in group chats (true/false)"},
"omemo": configurationOption{"<on|auto|off>", "account-wide OMEMO encryption mode - see /omemo for a dedicated command and per-chat overrides"}, "omemo": configurationOption{"<on|auto|off>", "account-wide OMEMO encryption mode (use /omemo in a chat for per-chat overrides and device trust)"},
} }
type command struct { type command struct {
@ -575,17 +574,6 @@ func (c *Client) ProcessTransportCommand(cmdline string, resource string) (strin
cancelNextStage = true cancelNextStage = true
return "Invalid argument. Allowed ones are " + transportCommands["preset"].Arguments[0], false return "Invalid argument. Allowed ones are " + transportCommands["preset"].Arguments[0], false
} }
case "omemo":
if len(args) > 0 {
value, err := c.Session.Set("omemo", args[0])
if err != nil {
return err.Error(), false
}
gateway.DirtySessions = true
return fmt.Sprintf("omemo mode set to %s", value), true
}
value, _ := c.Session.Get("omemo")
return fmt.Sprintf("omemo mode is set to %s (per-chat overrides: use /omemo on|off|clear in a chat)", value), true
case "pass": case "pass":
switch c.loginStage { switch c.loginStage {
case LoginStagePreset: case LoginStagePreset:

View file

@ -1902,14 +1902,10 @@ func handleSetQueryCommand(s xmpp.Sender, iq *stanza.IQ, command *stanza.Command
CommandElements: elements, CommandElements: elements,
} }
} }
} else if command.Node == "omemo" { } else if toOk && command.Node == "omemo" {
session, ok := sessions[bare] session, ok := sessions[bare]
if ok { if ok {
if toOk { answer.Payload = submitOmemoChatForm(session, toId, form)
answer.Payload = submitOmemoChatForm(session, toId, form)
} else {
answer.Payload = submitOmemoTransportForm(session, form)
}
} }
} else if !toOk && command.Node == "loginwizard" { } else if !toOk && command.Node == "loginwizard" {
var session *telegram.Client var session *telegram.Client
@ -1990,28 +1986,33 @@ func handleSetQueryCommand(s xmpp.Sender, iq *stanza.IQ, command *stanza.Command
} }
var fieldType string var fieldType string
var options []stanza.Option
if persistence.PropertyType(key) == persistence.PropertyTypeBool { if persistence.PropertyType(key) == persistence.PropertyTypeBool {
fieldType = stanza.FieldTypeBool fieldType = stanza.FieldTypeBool
} else if key == "omemo" {
fieldType = stanza.FieldTypeListSingle
options = []stanza.Option{
{Label: "Automatic (default)", ValuesList: []string{"auto"}},
{Label: "Always on", ValuesList: []string{"on"}},
{Label: "Always off", ValuesList: []string{"off"}},
}
} }
field := stanza.Field{ field := stanza.Field{
Var: key, Var: key,
Label: key, Label: key,
Type: fieldType, Type: fieldType,
Options: options,
ValuesList: []string{value}, ValuesList: []string{value},
} }
fields = append(fields, &field) fields = append(fields, &field)
log.Debugf("field: %#v", field) log.Debugf("field: %#v", field)
} }
} }
} else if command.Node == "omemo" { } else if toOk && command.Node == "omemo" {
session, ok := sessions[bare] session, ok := sessions[bare]
if ok { if ok {
if toOk { fields = buildOmemoChatFormFields(session, toId)
fields = buildOmemoChatFormFields(session, toId)
} else {
fields = buildOmemoTransportFormFields(session)
}
} }
} else { } else {
for i, arg := range cmd.Arguments { for i, arg := range cmd.Arguments {
@ -2055,6 +2056,12 @@ func handleSetQueryCommand(s xmpp.Sender, iq *stanza.IQ, command *stanza.Command
} }
} }
} }
} else if !toOk && i == 0 && command.Node == "preset" {
fieldType = stanza.FieldTypeListSingle
options = []stanza.Option{
{Label: "Modern", ValuesList: []string{"modern"}},
{Label: "Classic", ValuesList: []string{"classic"}},
}
} }
field := stanza.Field{ field := stanza.Field{

View file

@ -4,35 +4,10 @@ import (
"fmt" "fmt"
"dev.narayana.im/narayana/telegabber/telegram" "dev.narayana.im/narayana/telegabber/telegram"
"dev.narayana.im/narayana/telegabber/xmpp/gateway"
"gosrc.io/xmpp/stanza" "gosrc.io/xmpp/stanza"
) )
// buildOmemoTransportFormFields builds the initial (no form submitted yet)
// field list for the transport-level "/omemo" ad-hoc command: a single
// list-single field for the account-wide mode, pre-selected to the current
// value. Plugs into handleSetQueryCommand's shared per-command
// field-then-form-then-answer construction, the same way "config"'s own
// field-building does.
func buildOmemoTransportFormFields(session *telegram.Client) []*stanza.Field {
mode, _ := session.Session.Get("omemo")
return []*stanza.Field{
{
Var: "mode",
Label: "OMEMO mode",
Type: stanza.FieldTypeListSingle,
Options: []stanza.Option{
{Label: "Automatic (default)", ValuesList: []string{"auto"}},
{Label: "Always on", ValuesList: []string{"on"}},
{Label: "Always off", ValuesList: []string{"off"}},
},
ValuesList: []string{mode},
},
}
}
// buildOmemoChatFormFields builds the initial field list for the // buildOmemoChatFormFields builds the initial field list for the
// chat-scoped "/omemo" ad-hoc command: a read-only effective-status field, // chat-scoped "/omemo" ad-hoc command: a read-only effective-status field,
// a list-single override control, and two list-single "block"/"accept" // a list-single override control, and two list-single "block"/"accept"
@ -95,32 +70,6 @@ func buildOmemoChatFormFields(session *telegram.Client, chatID int64) []*stanza.
) )
} }
// submitOmemoTransportForm applies a submitted transport-level "/omemo"
// form.
func submitOmemoTransportForm(session *telegram.Client, form *stanza.Form) *stanza.Command {
var mode string
for _, field := range form.Fields {
if field != nil && field.Var == "mode" && len(field.ValuesList) > 0 {
mode = field.ValuesList[0]
}
}
var note stanza.Note
if value, err := session.Session.Set("omemo", mode); err != nil {
note = stanza.Note{Text: err.Error(), Type: stanza.CommandNoteTypeErr}
} else {
gateway.DirtySessions = true
note = stanza.Note{Text: fmt.Sprintf("omemo mode set to %s", value), Type: stanza.CommandNoteTypeInfo}
}
return &stanza.Command{
SessionId: "omemo",
Node: "omemo",
Status: stanza.CommandStatusCompleted,
CommandElements: []stanza.CommandElement{&note},
}
}
// submitOmemoChatForm applies a submitted chat-scoped "/omemo" form: the // submitOmemoChatForm applies a submitted chat-scoped "/omemo" form: the
// override change (if submitted), then at most one block and one accept // override change (if submitted), then at most one block and one accept
// (each field is a single empty-or-one-device selection, not a multi-pick // (each field is a single empty-or-one-device selection, not a multi-pick