mirror of
https://dev.narayana.im/narayana/telegabber.git
synced 2026-08-05 04:07:07 +00:00
Ad-Hoc mapping for /omemo commands
This commit is contained in:
parent
aa7d31a4f7
commit
40c1a8ceff
3 changed files with 334 additions and 46 deletions
|
|
@ -1,6 +1,7 @@
|
||||||
package telegram
|
package telegram
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
|
@ -8,73 +9,145 @@ import (
|
||||||
"dev.narayana.im/narayana/telegabber/xmpp/gateway"
|
"dev.narayana.im/narayana/telegabber/xmpp/gateway"
|
||||||
)
|
)
|
||||||
|
|
||||||
// cmdOmemoChat implements the chat-scoped "/omemo" command: with no
|
// OmemoDeviceStatus is one known device of a chat's peer - shared data
|
||||||
// arguments, reports this chat's current OMEMO state (account-wide mode,
|
// backing both the text "/omemo devices" command and the ad-hoc command's
|
||||||
// any override, and the resulting effective state); "on"/"off" forces this
|
// form (xmpp/omemo_command.go), so both surfaces always agree.
|
||||||
// specific chat regardless of the account-wide mode (persistence.Session.OMEMO,
|
type OmemoDeviceStatus struct {
|
||||||
// via e2ee.Mode/e2ee.ShouldEncrypt); "clear" removes that override, reverting
|
ID string
|
||||||
// to following the account-wide mode; "devices ..." manages this chat's
|
Trusted bool
|
||||||
// peer's device trust (see cmdOmemoDevices).
|
}
|
||||||
func (c *Client) cmdOmemoChat(chatID int64, args []string) (string, bool) {
|
|
||||||
|
// OmemoChatStatus is a chat's current OMEMO state - shared data backing
|
||||||
|
// both the text "/omemo" command and the ad-hoc command's form.
|
||||||
|
type OmemoChatStatus struct {
|
||||||
|
Mode string // account-wide mode: "on"/"auto"/"off" (e2ee.Mode.String())
|
||||||
|
OverrideSet bool
|
||||||
|
Override bool // meaningful only if OverrideSet
|
||||||
|
Effective bool // e2ee.ShouldEncrypt's actual verdict right now
|
||||||
|
Devices []OmemoDeviceStatus
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetOmemoChatStatus reports chatID's current OMEMO state.
|
||||||
|
func (c *Client) GetOmemoChatStatus(chatID int64) (OmemoChatStatus, error) {
|
||||||
backend, ok := gateway.E2EE.Backend()
|
backend, ok := gateway.E2EE.Backend()
|
||||||
if !ok {
|
if !ok {
|
||||||
return "OMEMO is not enabled on this transport", false
|
return OmemoChatStatus{}, errors.New("OMEMO is not enabled on this transport")
|
||||||
}
|
}
|
||||||
owner := e2ee.OwnedPeer(c.Session.Login, gateway.CHATJID(chatID, false))
|
owner := e2ee.OwnedPeer(c.Session.Login, gateway.CHATJID(chatID, false))
|
||||||
|
|
||||||
|
mode, err := e2ee.ParseMode(c.Session.OMEMO)
|
||||||
|
if err != nil {
|
||||||
|
return OmemoChatStatus{}, err
|
||||||
|
}
|
||||||
|
override, isSet, err := backend.Override(owner)
|
||||||
|
if err != nil {
|
||||||
|
return OmemoChatStatus{}, err
|
||||||
|
}
|
||||||
|
active, err := e2ee.ShouldEncrypt(backend, owner, mode)
|
||||||
|
if err != nil {
|
||||||
|
return OmemoChatStatus{}, err
|
||||||
|
}
|
||||||
|
devices, err := backend.Devices(owner, e2ee.PeerID(c.jid))
|
||||||
|
if err != nil {
|
||||||
|
return OmemoChatStatus{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
statuses := make([]OmemoDeviceStatus, len(devices))
|
||||||
|
for i, d := range devices {
|
||||||
|
statuses[i] = OmemoDeviceStatus{ID: string(d.ID), Trusted: d.Trusted}
|
||||||
|
}
|
||||||
|
|
||||||
|
return OmemoChatStatus{
|
||||||
|
Mode: mode.String(),
|
||||||
|
OverrideSet: isSet,
|
||||||
|
Override: override,
|
||||||
|
Effective: active,
|
||||||
|
Devices: statuses,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetOmemoChatOverride forces (on non-nil) or clears (on nil) chatID's
|
||||||
|
// OMEMO override.
|
||||||
|
func (c *Client) SetOmemoChatOverride(chatID int64, on *bool) error {
|
||||||
|
backend, ok := gateway.E2EE.Backend()
|
||||||
|
if !ok {
|
||||||
|
return errors.New("OMEMO is not enabled on this transport")
|
||||||
|
}
|
||||||
|
owner := e2ee.OwnedPeer(c.Session.Login, gateway.CHATJID(chatID, false))
|
||||||
|
if on == nil {
|
||||||
|
return backend.ClearOverride(owner)
|
||||||
|
}
|
||||||
|
return backend.SetOverride(owner, *on)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetOmemoDeviceBlocked blocks or unblocks one of chatID's peer's devices.
|
||||||
|
func (c *Client) SetOmemoDeviceBlocked(chatID int64, deviceID string, blocked bool) error {
|
||||||
|
backend, ok := gateway.E2EE.Backend()
|
||||||
|
if !ok {
|
||||||
|
return errors.New("OMEMO is not enabled on this transport")
|
||||||
|
}
|
||||||
|
owner := e2ee.OwnedPeer(c.Session.Login, gateway.CHATJID(chatID, false))
|
||||||
|
peer := e2ee.PeerID(c.jid)
|
||||||
|
if blocked {
|
||||||
|
return backend.BlockDevice(owner, peer, e2ee.DeviceID(deviceID))
|
||||||
|
}
|
||||||
|
return backend.UnblockDevice(owner, peer, e2ee.DeviceID(deviceID))
|
||||||
|
}
|
||||||
|
|
||||||
|
// cmdOmemoChat implements the chat-scoped "/omemo" text command: with no
|
||||||
|
// arguments, reports this chat's current OMEMO state (account-wide mode,
|
||||||
|
// any override, and the resulting effective state); "on"/"off" forces this
|
||||||
|
// specific chat regardless of the account-wide mode; "clear" removes that
|
||||||
|
// override, reverting to following the account-wide mode; "devices ..."
|
||||||
|
// manages this chat's peer's device trust (see cmdOmemoDevices). The
|
||||||
|
// ad-hoc command surface (xmpp/omemo_command.go) offers the same controls
|
||||||
|
// as a form, built from the same GetOmemoChatStatus/SetOmemoChatOverride/
|
||||||
|
// SetOmemoDeviceBlocked methods this uses.
|
||||||
|
func (c *Client) cmdOmemoChat(chatID int64, args []string) (string, bool) {
|
||||||
if len(args) == 0 {
|
if len(args) == 0 {
|
||||||
return c.omemoChatStatus(backend, owner)
|
return c.omemoChatStatusString(chatID)
|
||||||
}
|
}
|
||||||
|
|
||||||
switch args[0] {
|
switch args[0] {
|
||||||
case "on", "off":
|
case "on", "off":
|
||||||
if err := backend.SetOverride(owner, args[0] == "on"); err != nil {
|
on := args[0] == "on"
|
||||||
|
if err := c.SetOmemoChatOverride(chatID, &on); err != nil {
|
||||||
return err.Error(), false
|
return err.Error(), false
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("OMEMO forced %s for this chat", args[0]), true
|
return fmt.Sprintf("OMEMO forced %s for this chat", args[0]), true
|
||||||
case "clear":
|
case "clear":
|
||||||
if err := backend.ClearOverride(owner); err != nil {
|
if err := c.SetOmemoChatOverride(chatID, nil); err != nil {
|
||||||
return err.Error(), false
|
return err.Error(), false
|
||||||
}
|
}
|
||||||
return "OMEMO override cleared for this chat, now following the account-wide mode", true
|
return "OMEMO override cleared for this chat, now following the account-wide mode", true
|
||||||
case "devices":
|
case "devices":
|
||||||
return c.cmdOmemoDevices(backend, owner, args[1:])
|
return c.cmdOmemoDevices(chatID, args[1:])
|
||||||
default:
|
default:
|
||||||
return "Usage: /omemo [on|off|clear|devices list|devices block <id>|devices accept <id>]", false
|
return "Usage: /omemo [on|off|clear|devices list|devices block <id>|devices accept <id>]", false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) omemoChatStatus(backend e2ee.Backend, owner e2ee.PeerID) (string, bool) {
|
func (c *Client) omemoChatStatusString(chatID int64) (string, bool) {
|
||||||
mode, err := e2ee.ParseMode(c.Session.OMEMO)
|
status, err := c.GetOmemoChatStatus(chatID)
|
||||||
if err != nil {
|
|
||||||
return err.Error(), false
|
|
||||||
}
|
|
||||||
override, isSet, err := backend.Override(owner)
|
|
||||||
if err != nil {
|
|
||||||
return err.Error(), false
|
|
||||||
}
|
|
||||||
active, err := e2ee.ShouldEncrypt(backend, owner, mode)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err.Error(), false
|
return err.Error(), false
|
||||||
}
|
}
|
||||||
|
|
||||||
overrideText := "not set (following the account-wide mode)"
|
overrideText := "not set (following the account-wide mode)"
|
||||||
if isSet {
|
if status.OverrideSet {
|
||||||
overrideText = fmt.Sprintf("forced %s", onOffString(override))
|
overrideText = fmt.Sprintf("forced %s", onOffString(status.Override))
|
||||||
}
|
}
|
||||||
|
|
||||||
return fmt.Sprintf("Account-wide mode: %s\nThis chat's override: %s\nEffective right now: %s",
|
return fmt.Sprintf("Account-wide mode: %s\nThis chat's override: %s\nEffective right now: %s",
|
||||||
mode, overrideText, onOffString(active)), true
|
status.Mode, overrideText, onOffString(status.Effective)), true
|
||||||
}
|
}
|
||||||
|
|
||||||
// cmdOmemoDevices lists, blocks, or accepts (unblocks) devices of owner's
|
// cmdOmemoDevices lists, blocks, or accepts (unblocks) devices of chatID's
|
||||||
// chat's real peer. TOFU trust itself always stays on (a never-before-seen
|
// real peer. TOFU trust itself always stays on (a never-before-seen
|
||||||
// device is always trusted automatically) - block/accept only manage a
|
// device is always trusted automatically) - block/accept only manage a
|
||||||
// manual override layered on top of that, per Backend.BlockDevice's doc
|
// manual override layered on top of that, per e2ee.Backend.BlockDevice's
|
||||||
// comment.
|
// doc comment.
|
||||||
func (c *Client) cmdOmemoDevices(backend e2ee.Backend, owner e2ee.PeerID, args []string) (string, bool) {
|
func (c *Client) cmdOmemoDevices(chatID int64, args []string) (string, bool) {
|
||||||
peer := e2ee.PeerID(c.jid)
|
|
||||||
|
|
||||||
sub := "list"
|
sub := "list"
|
||||||
if len(args) > 0 {
|
if len(args) > 0 {
|
||||||
sub = args[0]
|
sub = args[0]
|
||||||
|
|
@ -82,15 +155,15 @@ func (c *Client) cmdOmemoDevices(backend e2ee.Backend, owner e2ee.PeerID, args [
|
||||||
|
|
||||||
switch sub {
|
switch sub {
|
||||||
case "list":
|
case "list":
|
||||||
devices, err := backend.Devices(owner, peer)
|
status, err := c.GetOmemoChatStatus(chatID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err.Error(), false
|
return err.Error(), false
|
||||||
}
|
}
|
||||||
if len(devices) == 0 {
|
if len(status.Devices) == 0 {
|
||||||
return "No known devices for this chat's peer yet", true
|
return "No known devices for this chat's peer yet", true
|
||||||
}
|
}
|
||||||
lines := make([]string, 0, len(devices))
|
lines := make([]string, 0, len(status.Devices))
|
||||||
for _, d := range devices {
|
for _, d := range status.Devices {
|
||||||
lines = append(lines, fmt.Sprintf("%s: %s", d.ID, trustString(d.Trusted)))
|
lines = append(lines, fmt.Sprintf("%s: %s", d.ID, trustString(d.Trusted)))
|
||||||
}
|
}
|
||||||
return strings.Join(lines, "\n"), true
|
return strings.Join(lines, "\n"), true
|
||||||
|
|
@ -98,17 +171,10 @@ func (c *Client) cmdOmemoDevices(backend e2ee.Backend, owner e2ee.PeerID, args [
|
||||||
if len(args) < 2 {
|
if len(args) < 2 {
|
||||||
return notEnoughArguments, false
|
return notEnoughArguments, false
|
||||||
}
|
}
|
||||||
device := e2ee.DeviceID(args[1])
|
if err := c.SetOmemoDeviceBlocked(chatID, args[1], sub == "block"); err != nil {
|
||||||
var err error
|
|
||||||
if sub == "block" {
|
|
||||||
err = backend.BlockDevice(owner, peer, device)
|
|
||||||
} else {
|
|
||||||
err = backend.UnblockDevice(owner, peer, device)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return err.Error(), false
|
return err.Error(), false
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("Device %s %sed", device, sub), true
|
return fmt.Sprintf("Device %s %sed", args[1], sub), true
|
||||||
default:
|
default:
|
||||||
return "Usage: /omemo devices [list|block <id>|accept <id>]", false
|
return "Usage: /omemo devices [list|block <id>|accept <id>]", false
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1859,6 +1859,15 @@ func handleSetQueryCommand(s xmpp.Sender, iq *stanza.IQ, command *stanza.Command
|
||||||
CommandElements: elements,
|
CommandElements: elements,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if command.Node == "omemo" {
|
||||||
|
session, ok := sessions[bare]
|
||||||
|
if ok {
|
||||||
|
if toOk {
|
||||||
|
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
|
||||||
answer.Payload, cancelSend, session = loginWizardPayload(bare, form, resource, command.Action)
|
answer.Payload, cancelSend, session = loginWizardPayload(bare, form, resource, command.Action)
|
||||||
|
|
@ -1952,6 +1961,15 @@ func handleSetQueryCommand(s xmpp.Sender, iq *stanza.IQ, command *stanza.Command
|
||||||
log.Debugf("field: %#v", field)
|
log.Debugf("field: %#v", field)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if command.Node == "omemo" {
|
||||||
|
session, ok := sessions[bare]
|
||||||
|
if ok {
|
||||||
|
if toOk {
|
||||||
|
fields = buildOmemoChatFormFields(session, toId)
|
||||||
|
} else {
|
||||||
|
fields = buildOmemoTransportFormFields(session)
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
for i, arg := range cmd.Arguments {
|
for i, arg := range cmd.Arguments {
|
||||||
var required *string
|
var required *string
|
||||||
|
|
|
||||||
204
xmpp/omemo_command.go
Normal file
204
xmpp/omemo_command.go
Normal file
|
|
@ -0,0 +1,204 @@
|
||||||
|
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"
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue