mirror of
https://dev.narayana.im/narayana/telegabber.git
synced 2026-08-05 12:17:06 +00:00
204 lines
6.9 KiB
Go
204 lines
6.9 KiB
Go
package xmpp
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"dev.narayana.im/narayana/telegabber/telegram"
|
|
"dev.narayana.im/narayana/telegabber/xmpp/gateway"
|
|
|
|
"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
|
|
// chat-scoped "/omemo" ad-hoc command: a read-only effective-status field,
|
|
// a list-single override control, and two list-single "block"/"accept"
|
|
// fields - each an empty-by-default choice (no selection = no action)
|
|
// among the CURRENT opposite-state devices (block's options are the
|
|
// currently-trusted devices, accept's are the currently-blocked ones).
|
|
// This mirrors handleSetQueryCommand's existing mute/kick/ban/unmute/unban
|
|
// field-building exactly (a list-single of opposite-state members with a
|
|
// blank leading option), rather than a separate reported/item table plus
|
|
// list-multi fields - one form field per action, same as those commands.
|
|
func buildOmemoChatFormFields(session *telegram.Client, chatID int64) []*stanza.Field {
|
|
status, err := session.GetOmemoChatStatus(chatID)
|
|
if err != nil {
|
|
return []*stanza.Field{
|
|
{Type: stanza.FieldTypeFixed, Label: "Error", ValuesList: []string{err.Error()}},
|
|
}
|
|
}
|
|
|
|
overrideValue := ""
|
|
if status.OverrideSet {
|
|
overrideValue = omemoOnOff(status.Override)
|
|
}
|
|
|
|
fields := []*stanza.Field{
|
|
{
|
|
Var: "effective",
|
|
Label: "Effective right now",
|
|
Type: stanza.FieldTypeFixed,
|
|
ValuesList: []string{fmt.Sprintf("%s (account-wide mode: %s)", omemoOnOff(status.Effective), status.Mode)},
|
|
},
|
|
{
|
|
Var: "override",
|
|
Label: "Override for this chat",
|
|
Type: stanza.FieldTypeListSingle,
|
|
Options: []stanza.Option{
|
|
{Label: "Follow account-wide mode", ValuesList: []string{""}},
|
|
{Label: "Always on", ValuesList: []string{"on"}},
|
|
{Label: "Always off", ValuesList: []string{"off"}},
|
|
},
|
|
ValuesList: []string{overrideValue},
|
|
},
|
|
}
|
|
|
|
// allow an empty selection ("no action"), same as mute/unmute's own
|
|
// blank leading option
|
|
blockOptions := []stanza.Option{{ValuesList: []string{""}}}
|
|
acceptOptions := []stanza.Option{{ValuesList: []string{""}}}
|
|
for _, d := range status.Devices {
|
|
option := stanza.Option{Label: d.ID, ValuesList: []string{d.ID}}
|
|
if d.Trusted {
|
|
blockOptions = append(blockOptions, option)
|
|
} else {
|
|
acceptOptions = append(acceptOptions, option)
|
|
}
|
|
}
|
|
|
|
return append(fields,
|
|
&stanza.Field{Var: "block", Label: "Block device", Type: stanza.FieldTypeListSingle, Options: blockOptions},
|
|
&stanza.Field{Var: "accept", Label: "Accept (unblock) device", Type: stanza.FieldTypeListSingle, Options: acceptOptions},
|
|
)
|
|
}
|
|
|
|
// 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{¬e},
|
|
}
|
|
}
|
|
|
|
// submitOmemoChatForm applies a submitted chat-scoped "/omemo" form: the
|
|
// 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
|
|
// - see buildOmemoChatFormFields) - all in one round trip, since XEP-0050
|
|
// single-stage commands only get one.
|
|
func submitOmemoChatForm(session *telegram.Client, chatID int64, form *stanza.Form) *stanza.Command {
|
|
var overrideValue string
|
|
var overrideSubmitted bool
|
|
var blockID, acceptID string
|
|
for _, field := range form.Fields {
|
|
if field == nil {
|
|
continue
|
|
}
|
|
switch field.Var {
|
|
case "override":
|
|
overrideSubmitted = true
|
|
if len(field.ValuesList) > 0 {
|
|
overrideValue = field.ValuesList[0]
|
|
}
|
|
case "block":
|
|
if len(field.ValuesList) > 0 {
|
|
blockID = field.ValuesList[0]
|
|
}
|
|
case "accept":
|
|
if len(field.ValuesList) > 0 {
|
|
acceptID = field.ValuesList[0]
|
|
}
|
|
}
|
|
}
|
|
|
|
var notes []stanza.CommandElement
|
|
if overrideSubmitted {
|
|
switch overrideValue {
|
|
case "":
|
|
if err := session.SetOmemoChatOverride(chatID, nil); err != nil {
|
|
notes = append(notes, &stanza.Note{Text: err.Error(), Type: stanza.CommandNoteTypeErr})
|
|
} else {
|
|
notes = append(notes, &stanza.Note{Text: "OMEMO override cleared for this chat", Type: stanza.CommandNoteTypeInfo})
|
|
}
|
|
case "on", "off":
|
|
on := overrideValue == "on"
|
|
if err := session.SetOmemoChatOverride(chatID, &on); err != nil {
|
|
notes = append(notes, &stanza.Note{Text: err.Error(), Type: stanza.CommandNoteTypeErr})
|
|
} else {
|
|
notes = append(notes, &stanza.Note{Text: fmt.Sprintf("OMEMO forced %s for this chat", overrideValue), Type: stanza.CommandNoteTypeInfo})
|
|
}
|
|
}
|
|
}
|
|
|
|
if blockID != "" {
|
|
if err := session.SetOmemoDeviceBlocked(chatID, blockID, true); err != nil {
|
|
notes = append(notes, &stanza.Note{Text: fmt.Sprintf("Failed to block device %s: %v", blockID, err), Type: stanza.CommandNoteTypeErr})
|
|
} else {
|
|
notes = append(notes, &stanza.Note{Text: fmt.Sprintf("Device %s blocked", blockID), Type: stanza.CommandNoteTypeInfo})
|
|
}
|
|
}
|
|
if acceptID != "" {
|
|
if err := session.SetOmemoDeviceBlocked(chatID, acceptID, false); err != nil {
|
|
notes = append(notes, &stanza.Note{Text: fmt.Sprintf("Failed to accept device %s: %v", acceptID, err), Type: stanza.CommandNoteTypeErr})
|
|
} else {
|
|
notes = append(notes, &stanza.Note{Text: fmt.Sprintf("Device %s accepted", acceptID), Type: stanza.CommandNoteTypeInfo})
|
|
}
|
|
}
|
|
if len(notes) == 0 {
|
|
notes = append(notes, &stanza.Note{Text: "No changes", Type: stanza.CommandNoteTypeInfo})
|
|
}
|
|
|
|
return &stanza.Command{
|
|
SessionId: "omemo",
|
|
Node: "omemo",
|
|
Status: stanza.CommandStatusCompleted,
|
|
CommandElements: notes,
|
|
}
|
|
}
|
|
|
|
func omemoOnOff(b bool) string {
|
|
if b {
|
|
return "on"
|
|
}
|
|
return "off"
|
|
}
|