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",
|
||||
"version": {
|
||||
"name": "signald",
|
||||
"version": "0.12.0+git2021-02-08r98148393.17",
|
||||
"version": "0.12.0+git2021-02-12r1f18d539.24",
|
||||
"branch": "main",
|
||||
"commit": "9814839376b0aceed8329fecc7477a5da7d0cae8"
|
||||
"commit": "1f18d539bb0d09ea51948e9559ab5e04ca9359a5"
|
||||
},
|
||||
"info": "This document describes objects that may be used when communicating with signald.",
|
||||
"types": {
|
||||
|
@ -34,7 +34,7 @@
|
|||
},
|
||||
"timestamp": {
|
||||
"type": "long",
|
||||
"example": "1612746778552"
|
||||
"example": "1613092537706"
|
||||
},
|
||||
"timestampISO": {
|
||||
"type": "String"
|
||||
|
@ -44,7 +44,7 @@
|
|||
},
|
||||
"serverDeliveredTimestamp": {
|
||||
"type": "long",
|
||||
"example": "161274677855280"
|
||||
"example": "161309253770680"
|
||||
},
|
||||
"hasLegacyMessage": {
|
||||
"type": "boolean"
|
||||
|
@ -124,7 +124,7 @@
|
|||
},
|
||||
"timestamp": {
|
||||
"type": "long",
|
||||
"example": "1612746778552"
|
||||
"example": "1613092537706"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -165,7 +165,7 @@
|
|||
},
|
||||
"version": {
|
||||
"type": "String",
|
||||
"example": "\"0.12.0+git2021-02-08r98148393.17\""
|
||||
"example": "\"0.12.0+git2021-02-12r1f18d539.24\""
|
||||
},
|
||||
"branch": {
|
||||
"type": "String",
|
||||
|
@ -173,7 +173,7 @@
|
|||
},
|
||||
"commit": {
|
||||
"type": "String",
|
||||
"example": "\"9814839376b0aceed8329fecc7477a5da7d0cae8\""
|
||||
"example": "\"1f18d539bb0d09ea51948e9559ab5e04ca9359a5\""
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -517,7 +517,7 @@
|
|||
"list": true,
|
||||
"type": "Long",
|
||||
"doc": "List of messages to mark as read",
|
||||
"example": "1612746778552",
|
||||
"example": "1613092537706",
|
||||
"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": {
|
||||
"fields": {
|
||||
"timestamp": {
|
||||
"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.",
|
||||
"example": "1612746778552"
|
||||
"example": "1613092537706"
|
||||
},
|
||||
"attachments": {
|
||||
"list": true,
|
||||
|
@ -762,7 +811,7 @@
|
|||
"id": {
|
||||
"type": "long",
|
||||
"doc": "the client timestamp of the message being quoted",
|
||||
"example": "1612746778552"
|
||||
"example": "1613092537706"
|
||||
},
|
||||
"author": {
|
||||
"type": "JsonAddress",
|
||||
|
@ -850,7 +899,7 @@
|
|||
"targetSentTimestamp": {
|
||||
"type": "long",
|
||||
"doc": "the client timestamp of the message being reacted to",
|
||||
"example": "1612746778552"
|
||||
"example": "1613092537706"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -930,7 +979,7 @@
|
|||
},
|
||||
"timestamp": {
|
||||
"type": "long",
|
||||
"example": "1612746778552"
|
||||
"example": "1613092537706"
|
||||
},
|
||||
"expirationStartTimestamp": {
|
||||
"type": "long"
|
||||
|
@ -968,7 +1017,7 @@
|
|||
},
|
||||
"timestamp": {
|
||||
"type": "long",
|
||||
"example": "1612746778552"
|
||||
"example": "1613092537706"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -980,7 +1029,7 @@
|
|||
},
|
||||
"timestamp": {
|
||||
"type": "long",
|
||||
"example": "1612746778552"
|
||||
"example": "1613092537706"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -1746,6 +1795,14 @@
|
|||
"list_contacts": {
|
||||
"request": "ListContactsRequest",
|
||||
"response": "ProfileList"
|
||||
},
|
||||
"create_group": {
|
||||
"request": "CreateGroupRequest",
|
||||
"response": "JsonGroupV2Info"
|
||||
},
|
||||
"leave_group": {
|
||||
"request": "LeaveGroupRequest",
|
||||
"response": "GroupInfo"
|
||||
}
|
||||
},
|
||||
"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
|
||||
func (r *GetGroupRequest) Submit(conn *signald.Signald) (response JsonGroupV2Info, err error) {
|
||||
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) {
|
||||
r.Version = "v1"
|
||||
r.Type = "list_contacts"
|
||||
|
|
|
@ -33,6 +33,16 @@ type Capabilities struct {
|
|||
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
|
||||
type GetGroupRequest struct {
|
||||
Request
|
||||
|
@ -254,6 +264,12 @@ type JsonViewOnceOpenMessage struct {
|
|||
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 {
|
||||
Devices []*v0.DeviceInfo `json:"devices,omitempty" yaml:"devices,omitempty"`
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue