Update protocol and add group leave command
This commit is contained in:
parent
8c7e571188
commit
2f84cb4f3c
4 changed files with 239 additions and 14 deletions
88
cmd/signaldctl/cmd/group/leave/leave-group.go
Normal file
88
cmd/signaldctl/cmd/group/leave/leave-group.go
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
// Copyright © 2021 Finn Herzfeld <finn@janky.solutions>
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
package leave
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/jedib0t/go-pretty/v6/table"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
"gopkg.in/yaml.v2"
|
||||||
|
|
||||||
|
"gitlab.com/signald/signald-go/cmd/signaldctl/common"
|
||||||
|
"gitlab.com/signald/signald-go/cmd/signaldctl/config"
|
||||||
|
"gitlab.com/signald/signald-go/signald/client-protocol/v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
account string
|
||||||
|
LeaveGroupCmd = &cobra.Command{
|
||||||
|
Use: "leave <group id>",
|
||||||
|
Short: "leave a group (or decline an invitation to a group)",
|
||||||
|
PreRun: func(cmd *cobra.Command, args []string) {
|
||||||
|
if account == "" {
|
||||||
|
account = config.Config.DefaultAccount
|
||||||
|
}
|
||||||
|
if account == "" {
|
||||||
|
log.Fatal("No account specified. Please specify with --account or set a default")
|
||||||
|
}
|
||||||
|
if len(args) == 0 {
|
||||||
|
common.Must(cmd.Help())
|
||||||
|
log.Fatal("must specify a group ID")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Run: func(_ *cobra.Command, args []string) {
|
||||||
|
go common.Signald.Listen(nil)
|
||||||
|
req := v1.LeaveGroupRequest{Account: account, GroupID: args[0]}
|
||||||
|
resp, err := req.Submit(common.Signald)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err, "error communicating with signald")
|
||||||
|
}
|
||||||
|
|
||||||
|
switch common.OutputFormat {
|
||||||
|
case common.OutputFormatJSON:
|
||||||
|
err := json.NewEncoder(os.Stdout).Encode(resp)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err, "error encoding response to stdout")
|
||||||
|
}
|
||||||
|
case common.OutputFormatYAML:
|
||||||
|
err := yaml.NewEncoder(os.Stdout).Encode(resp)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err, "error encoding response to stdout")
|
||||||
|
}
|
||||||
|
case common.OutputFormatCSV, common.OutputFormatTable, common.OutputFormatDefault:
|
||||||
|
t := table.NewWriter()
|
||||||
|
t.SetOutputMirror(os.Stdout)
|
||||||
|
t.AppendHeader(table.Row{"ID", "Title", "Members"})
|
||||||
|
t.AppendRow(table.Row{resp.V2.ID, resp.V2.Title, len(resp.V2.Members)})
|
||||||
|
if common.OutputFormat == common.OutputFormatCSV {
|
||||||
|
t.RenderCSV()
|
||||||
|
} else {
|
||||||
|
common.StylizeTable(t)
|
||||||
|
t.Render()
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
log.Fatal("Unsupported output format")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
AcceptGroupInvitationCmd.Flags().StringVarP(&account, "account", "a", "", "the signald account to use")
|
||||||
|
}
|
|
@ -2,9 +2,9 @@
|
||||||
"doc_version": "v1",
|
"doc_version": "v1",
|
||||||
"version": {
|
"version": {
|
||||||
"name": "signald",
|
"name": "signald",
|
||||||
"version": "0.12.0+git2021-02-08r98148393.17",
|
"version": "0.12.0+git2021-02-12r1f18d539.24",
|
||||||
"branch": "main",
|
"branch": "main",
|
||||||
"commit": "9814839376b0aceed8329fecc7477a5da7d0cae8"
|
"commit": "1f18d539bb0d09ea51948e9559ab5e04ca9359a5"
|
||||||
},
|
},
|
||||||
"info": "This document describes objects that may be used when communicating with signald.",
|
"info": "This document describes objects that may be used when communicating with signald.",
|
||||||
"types": {
|
"types": {
|
||||||
|
@ -34,7 +34,7 @@
|
||||||
},
|
},
|
||||||
"timestamp": {
|
"timestamp": {
|
||||||
"type": "long",
|
"type": "long",
|
||||||
"example": "1612746778552"
|
"example": "1613092537706"
|
||||||
},
|
},
|
||||||
"timestampISO": {
|
"timestampISO": {
|
||||||
"type": "String"
|
"type": "String"
|
||||||
|
@ -44,7 +44,7 @@
|
||||||
},
|
},
|
||||||
"serverDeliveredTimestamp": {
|
"serverDeliveredTimestamp": {
|
||||||
"type": "long",
|
"type": "long",
|
||||||
"example": "161274677855280"
|
"example": "161309253770680"
|
||||||
},
|
},
|
||||||
"hasLegacyMessage": {
|
"hasLegacyMessage": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
|
@ -124,7 +124,7 @@
|
||||||
},
|
},
|
||||||
"timestamp": {
|
"timestamp": {
|
||||||
"type": "long",
|
"type": "long",
|
||||||
"example": "1612746778552"
|
"example": "1613092537706"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -165,7 +165,7 @@
|
||||||
},
|
},
|
||||||
"version": {
|
"version": {
|
||||||
"type": "String",
|
"type": "String",
|
||||||
"example": "\"0.12.0+git2021-02-08r98148393.17\""
|
"example": "\"0.12.0+git2021-02-12r1f18d539.24\""
|
||||||
},
|
},
|
||||||
"branch": {
|
"branch": {
|
||||||
"type": "String",
|
"type": "String",
|
||||||
|
@ -173,7 +173,7 @@
|
||||||
},
|
},
|
||||||
"commit": {
|
"commit": {
|
||||||
"type": "String",
|
"type": "String",
|
||||||
"example": "\"9814839376b0aceed8329fecc7477a5da7d0cae8\""
|
"example": "\"1f18d539bb0d09ea51948e9559ab5e04ca9359a5\""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -517,7 +517,7 @@
|
||||||
"list": true,
|
"list": true,
|
||||||
"type": "Long",
|
"type": "Long",
|
||||||
"doc": "List of messages to mark as read",
|
"doc": "List of messages to mark as read",
|
||||||
"example": "1612746778552",
|
"example": "1613092537706",
|
||||||
"required": true
|
"required": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -620,12 +620,61 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"CreateGroupRequest": {
|
||||||
|
"fields": {
|
||||||
|
"account": {
|
||||||
|
"type": "String",
|
||||||
|
"doc": "The account to interact with",
|
||||||
|
"example": "\"+12024561414\"",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
"title": {
|
||||||
|
"type": "String",
|
||||||
|
"example": "\"Parkdale Run Club\"",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
"avatar": {
|
||||||
|
"type": "String",
|
||||||
|
"example": "\"/tmp/image.jpg\""
|
||||||
|
},
|
||||||
|
"members": {
|
||||||
|
"list": true,
|
||||||
|
"type": "JsonAddress",
|
||||||
|
"version": "v1"
|
||||||
|
},
|
||||||
|
"timer": {
|
||||||
|
"type": "int",
|
||||||
|
"doc": "the message expiration timer"
|
||||||
|
},
|
||||||
|
"member_role": {
|
||||||
|
"type": "String",
|
||||||
|
"doc": "The role of all members other than the group creator. Options are ADMINISTRATOR or DEFAULT (case insensitive)",
|
||||||
|
"example": "\"ADMINISTRATOR\""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"LeaveGroupRequest": {
|
||||||
|
"fields": {
|
||||||
|
"account": {
|
||||||
|
"type": "String",
|
||||||
|
"doc": "The account to use",
|
||||||
|
"example": "\"+12024561414\"",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
"groupID": {
|
||||||
|
"type": "String",
|
||||||
|
"doc": "The group to leave",
|
||||||
|
"example": "\"EdSqI90cS0UomDpgUXOlCoObWvQOXlH5G3Z2d3f4ayE=\"",
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"JsonDataMessage": {
|
"JsonDataMessage": {
|
||||||
"fields": {
|
"fields": {
|
||||||
"timestamp": {
|
"timestamp": {
|
||||||
"type": "long",
|
"type": "long",
|
||||||
"doc": "the timestamp that the message was sent at, according to the sender's device. This is used to uniquely identify this message for things like reactions and quotes.",
|
"doc": "the timestamp that the message was sent at, according to the sender's device. This is used to uniquely identify this message for things like reactions and quotes.",
|
||||||
"example": "1612746778552"
|
"example": "1613092537706"
|
||||||
},
|
},
|
||||||
"attachments": {
|
"attachments": {
|
||||||
"list": true,
|
"list": true,
|
||||||
|
@ -762,7 +811,7 @@
|
||||||
"id": {
|
"id": {
|
||||||
"type": "long",
|
"type": "long",
|
||||||
"doc": "the client timestamp of the message being quoted",
|
"doc": "the client timestamp of the message being quoted",
|
||||||
"example": "1612746778552"
|
"example": "1613092537706"
|
||||||
},
|
},
|
||||||
"author": {
|
"author": {
|
||||||
"type": "JsonAddress",
|
"type": "JsonAddress",
|
||||||
|
@ -850,7 +899,7 @@
|
||||||
"targetSentTimestamp": {
|
"targetSentTimestamp": {
|
||||||
"type": "long",
|
"type": "long",
|
||||||
"doc": "the client timestamp of the message being reacted to",
|
"doc": "the client timestamp of the message being reacted to",
|
||||||
"example": "1612746778552"
|
"example": "1613092537706"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -930,7 +979,7 @@
|
||||||
},
|
},
|
||||||
"timestamp": {
|
"timestamp": {
|
||||||
"type": "long",
|
"type": "long",
|
||||||
"example": "1612746778552"
|
"example": "1613092537706"
|
||||||
},
|
},
|
||||||
"expirationStartTimestamp": {
|
"expirationStartTimestamp": {
|
||||||
"type": "long"
|
"type": "long"
|
||||||
|
@ -968,7 +1017,7 @@
|
||||||
},
|
},
|
||||||
"timestamp": {
|
"timestamp": {
|
||||||
"type": "long",
|
"type": "long",
|
||||||
"example": "1612746778552"
|
"example": "1613092537706"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -980,7 +1029,7 @@
|
||||||
},
|
},
|
||||||
"timestamp": {
|
"timestamp": {
|
||||||
"type": "long",
|
"type": "long",
|
||||||
"example": "1612746778552"
|
"example": "1613092537706"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -1746,6 +1795,14 @@
|
||||||
"list_contacts": {
|
"list_contacts": {
|
||||||
"request": "ListContactsRequest",
|
"request": "ListContactsRequest",
|
||||||
"response": "ProfileList"
|
"response": "ProfileList"
|
||||||
|
},
|
||||||
|
"create_group": {
|
||||||
|
"request": "CreateGroupRequest",
|
||||||
|
"response": "JsonGroupV2Info"
|
||||||
|
},
|
||||||
|
"leave_group": {
|
||||||
|
"request": "LeaveGroupRequest",
|
||||||
|
"response": "GroupInfo"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"v1alpha1": {
|
"v1alpha1": {
|
||||||
|
|
|
@ -76,6 +76,38 @@ func (r *ApproveMembershipRequest) Submit(conn *signald.Signald) (response JsonG
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *CreateGroupRequest) Submit(conn *signald.Signald) (response JsonGroupV2Info, err error) {
|
||||||
|
r.Version = "v1"
|
||||||
|
r.Type = "create_group"
|
||||||
|
if r.ID == "" {
|
||||||
|
r.ID = signald.GenerateID()
|
||||||
|
}
|
||||||
|
err = conn.RawRequest(r)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("signald-go: error submitting request to signald")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
responseChannel := conn.GetResponseListener(r.ID)
|
||||||
|
defer conn.CloseResponseListener(r.ID)
|
||||||
|
|
||||||
|
rawResponse := <-responseChannel
|
||||||
|
if rawResponse.Error != nil {
|
||||||
|
err = fmt.Errorf("signald error: %s", string(rawResponse.Error))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = json.Unmarshal(rawResponse.Data, &response)
|
||||||
|
if err != nil {
|
||||||
|
rawResponseJson, _ := rawResponse.Data.MarshalJSON()
|
||||||
|
log.Println("signald-go: error unmarshalling response from signald of type", rawResponse.Type, string(rawResponseJson))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return response, nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// Submit: Query the server for the latest state of a known group
|
// Submit: Query the server for the latest state of a known group
|
||||||
func (r *GetGroupRequest) Submit(conn *signald.Signald) (response JsonGroupV2Info, err error) {
|
func (r *GetGroupRequest) Submit(conn *signald.Signald) (response JsonGroupV2Info, err error) {
|
||||||
r.Version = "v1"
|
r.Version = "v1"
|
||||||
|
@ -208,6 +240,38 @@ func (r *JoinGroupRequest) Submit(conn *signald.Signald) (response JsonGroupJoin
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *LeaveGroupRequest) Submit(conn *signald.Signald) (response GroupInfo, err error) {
|
||||||
|
r.Version = "v1"
|
||||||
|
r.Type = "leave_group"
|
||||||
|
if r.ID == "" {
|
||||||
|
r.ID = signald.GenerateID()
|
||||||
|
}
|
||||||
|
err = conn.RawRequest(r)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("signald-go: error submitting request to signald")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
responseChannel := conn.GetResponseListener(r.ID)
|
||||||
|
defer conn.CloseResponseListener(r.ID)
|
||||||
|
|
||||||
|
rawResponse := <-responseChannel
|
||||||
|
if rawResponse.Error != nil {
|
||||||
|
err = fmt.Errorf("signald error: %s", string(rawResponse.Error))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = json.Unmarshal(rawResponse.Data, &response)
|
||||||
|
if err != nil {
|
||||||
|
rawResponseJson, _ := rawResponse.Data.MarshalJSON()
|
||||||
|
log.Println("signald-go: error unmarshalling response from signald of type", rawResponse.Type, string(rawResponseJson))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return response, nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
func (r *ListContactsRequest) Submit(conn *signald.Signald) (response ProfileList, err error) {
|
func (r *ListContactsRequest) Submit(conn *signald.Signald) (response ProfileList, err error) {
|
||||||
r.Version = "v1"
|
r.Version = "v1"
|
||||||
r.Type = "list_contacts"
|
r.Type = "list_contacts"
|
||||||
|
|
|
@ -33,6 +33,16 @@ type Capabilities struct {
|
||||||
Storage bool `json:"storage,omitempty" yaml:"storage,omitempty"`
|
Storage bool `json:"storage,omitempty" yaml:"storage,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type CreateGroupRequest struct {
|
||||||
|
Request
|
||||||
|
Account string `json:"account,omitempty" yaml:"account,omitempty"` // The account to interact with
|
||||||
|
Avatar string `json:"avatar,omitempty" yaml:"avatar,omitempty"`
|
||||||
|
Member_role string `json:"member_role,omitempty" yaml:"member_role,omitempty"` // The role of all members other than the group creator. Options are ADMINISTRATOR or DEFAULT (case insensitive)
|
||||||
|
Members []*JsonAddress `json:"members,omitempty" yaml:"members,omitempty"`
|
||||||
|
Timer int32 `json:"timer,omitempty" yaml:"timer,omitempty"` // the message expiration timer
|
||||||
|
Title string `json:"title,omitempty" yaml:"title,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
// GetGroupRequest: Query the server for the latest state of a known group
|
// GetGroupRequest: Query the server for the latest state of a known group
|
||||||
type GetGroupRequest struct {
|
type GetGroupRequest struct {
|
||||||
Request
|
Request
|
||||||
|
@ -254,6 +264,12 @@ type JsonViewOnceOpenMessage struct {
|
||||||
Timestamp int64 `json:"timestamp,omitempty" yaml:"timestamp,omitempty"`
|
Timestamp int64 `json:"timestamp,omitempty" yaml:"timestamp,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type LeaveGroupRequest struct {
|
||||||
|
Request
|
||||||
|
Account string `json:"account,omitempty" yaml:"account,omitempty"` // The account to use
|
||||||
|
GroupID string `json:"groupID,omitempty" yaml:"groupID,omitempty"` // The group to leave
|
||||||
|
}
|
||||||
|
|
||||||
type LinkedDevices struct {
|
type LinkedDevices struct {
|
||||||
Devices []*v0.DeviceInfo `json:"devices,omitempty" yaml:"devices,omitempty"`
|
Devices []*v0.DeviceInfo `json:"devices,omitempty" yaml:"devices,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue