Update protocol

This commit is contained in:
Finn 2021-01-29 16:45:29 -08:00
parent 9f5e5b2cb0
commit ff3bed1d9f
4 changed files with 222 additions and 53 deletions

View file

@ -2,9 +2,9 @@
"doc_version": "v1", "doc_version": "v1",
"version": { "version": {
"name": "signald", "name": "signald",
"version": "0.11.1+git2021-01-26r209ba8f1.66", "version": "0.11.1+git2021-01-30r350d7b78.75",
"branch": "main", "branch": "main",
"commit": "209ba8f1b1f472ca1fb2b0f1790f7cd1fad0658b" "commit": "350d7b78e6d8579866da07b9dc91035663e0b073"
}, },
"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": "1611698481651" "example": "1611966817808"
}, },
"timestampISO": { "timestampISO": {
"type": "String" "type": "String"
@ -44,7 +44,7 @@
}, },
"serverDeliveredTimestamp": { "serverDeliveredTimestamp": {
"type": "long", "type": "long",
"example": "161169848165180" "example": "161196681780880"
}, },
"hasLegacyMessage": { "hasLegacyMessage": {
"type": "boolean" "type": "boolean"
@ -81,7 +81,8 @@
"fields": { "fields": {
"username": { "username": {
"type": "String", "type": "String",
"example": "\"+12024561414\"" "example": "\"+12024561414\"",
"required": true
}, },
"recipientAddress": { "recipientAddress": {
"type": "JsonAddress", "type": "JsonAddress",
@ -123,7 +124,7 @@
}, },
"timestamp": { "timestamp": {
"type": "long", "type": "long",
"example": "1611698481651" "example": "1611966817808"
} }
} }
}, },
@ -131,7 +132,8 @@
"fields": { "fields": {
"username": { "username": {
"type": "String", "type": "String",
"example": "\"+12024561414\"" "example": "\"+12024561414\"",
"required": true
}, },
"recipientAddress": { "recipientAddress": {
"type": "JsonAddress", "type": "JsonAddress",
@ -143,7 +145,8 @@
}, },
"reaction": { "reaction": {
"type": "JsonReaction", "type": "JsonReaction",
"version": "v1" "version": "v1",
"required": true
}, },
"timestamp": { "timestamp": {
"type": "long" "type": "long"
@ -162,7 +165,7 @@
}, },
"version": { "version": {
"type": "String", "type": "String",
"example": "\"0.11.1+git2021-01-26r209ba8f1.66\"" "example": "\"0.11.1+git2021-01-30r350d7b78.75\""
}, },
"branch": { "branch": {
"type": "String", "type": "String",
@ -170,7 +173,7 @@
}, },
"commit": { "commit": {
"type": "String", "type": "String",
"example": "\"209ba8f1b1f472ca1fb2b0f1790f7cd1fad0658b\"" "example": "\"350d7b78e6d8579866da07b9dc91035663e0b073\""
} }
} }
}, },
@ -179,11 +182,13 @@
"account": { "account": {
"type": "String", "type": "String",
"doc": "The account to interact with", "doc": "The account to interact with",
"example": "\"+12024561414\"" "example": "\"+12024561414\"",
"required": true
}, },
"groupID": { "groupID": {
"type": "String", "type": "String",
"example": "\"EdSqI90cS0UomDpgUXOlCoObWvQOXlH5G3Z2d3f4ayE=\"" "example": "\"EdSqI90cS0UomDpgUXOlCoObWvQOXlH5G3Z2d3f4ayE=\"",
"required": true
} }
}, },
"doc": "Accept a v2 group invitation. Note that you must have a profile name set to join groups." "doc": "Accept a v2 group invitation. Note that you must have a profile name set to join groups."
@ -231,17 +236,20 @@
"account": { "account": {
"type": "String", "type": "String",
"doc": "The account to interact with", "doc": "The account to interact with",
"example": "\"+12024561414\"" "example": "\"+12024561414\"",
"required": true
}, },
"groupID": { "groupID": {
"type": "String", "type": "String",
"example": "\"EdSqI90cS0UomDpgUXOlCoObWvQOXlH5G3Z2d3f4ayE=\"" "example": "\"EdSqI90cS0UomDpgUXOlCoObWvQOXlH5G3Z2d3f4ayE=\"",
"required": true
}, },
"members": { "members": {
"list": true, "list": true,
"type": "JsonAddress", "type": "JsonAddress",
"version": "v1", "version": "v1",
"doc": "list of requesting members to approve" "doc": "list of requesting members to approve",
"required": true
} }
}, },
"doc": "approve a request to join a group" "doc": "approve a request to join a group"
@ -251,11 +259,13 @@
"account": { "account": {
"type": "String", "type": "String",
"doc": "The account to interact with", "doc": "The account to interact with",
"example": "\"+12024561414\"" "example": "\"+12024561414\"",
"required": true
}, },
"groupID": { "groupID": {
"type": "String", "type": "String",
"example": "\"EdSqI90cS0UomDpgUXOlCoObWvQOXlH5G3Z2d3f4ayE=\"" "example": "\"EdSqI90cS0UomDpgUXOlCoObWvQOXlH5G3Z2d3f4ayE=\"",
"required": true
}, },
"revision": { "revision": {
"type": "int", "type": "int",
@ -269,7 +279,8 @@
"account": { "account": {
"type": "String", "type": "String",
"doc": "The account to interact with", "doc": "The account to interact with",
"example": "\"+12024561414\"" "example": "\"+12024561414\"",
"required": true
} }
}, },
"doc": "list all linked devices on a Signal account" "doc": "list all linked devices on a Signal account"
@ -288,12 +299,14 @@
"account": { "account": {
"type": "String", "type": "String",
"doc": "The account to interact with", "doc": "The account to interact with",
"example": "\"+12024561414\"" "example": "\"+12024561414\"",
"required": true
}, },
"uri": { "uri": {
"type": "String", "type": "String",
"doc": "The signal.group URL", "doc": "The signal.group URL",
"example": "\"https://signal.group/#CjQKINH_GZhXhfifTcnBkaKTNRxW-hHKnGSq-cJNyPVqHRp8EhDUB7zjKNEl0NaULhsqJCX3\"" "example": "\"https://signal.group/#CjQKINH_GZhXhfifTcnBkaKTNRxW-hHKnGSq-cJNyPVqHRp8EhDUB7zjKNEl0NaULhsqJCX3\"",
"required": true
} }
}, },
"doc": "Join a group using the a signal.group URL. Note that you must have a profile name set to join groups." "doc": "Join a group using the a signal.group URL. Note that you must have a profile name set to join groups."
@ -332,12 +345,14 @@
"account": { "account": {
"type": "String", "type": "String",
"doc": "The account to interact with", "doc": "The account to interact with",
"example": "\"+12024561414\"" "example": "\"+12024561414\"",
"required": true
}, },
"deviceId": { "deviceId": {
"type": "long", "type": "long",
"doc": "the ID of the device to unlink", "doc": "the ID of the device to unlink",
"example": "3" "example": "3",
"required": true
} }
}, },
"doc": "Remove a linked device from the Signal account. Only allowed when the local device id is 1" "doc": "Remove a linked device from the Signal account. Only allowed when the local device id is 1"
@ -347,11 +362,13 @@
"account": { "account": {
"type": "String", "type": "String",
"doc": "The identifier of the account to interact with", "doc": "The identifier of the account to interact with",
"example": "\"+12024561414\"" "example": "\"+12024561414\"",
"required": true
}, },
"groupID": { "groupID": {
"type": "String", "type": "String",
"example": "\"EdSqI90cS0UomDpgUXOlCoObWvQOXlH5G3Z2d3f4ayE=\"" "example": "\"EdSqI90cS0UomDpgUXOlCoObWvQOXlH5G3Z2d3f4ayE=\"",
"required": true
}, },
"title": { "title": {
"type": "String", "type": "String",
@ -392,12 +409,14 @@
"account": { "account": {
"type": "String", "type": "String",
"doc": "The phone number of the account to use", "doc": "The phone number of the account to use",
"example": "\"+12024561414\"" "example": "\"+12024561414\"",
"required": true
}, },
"name": { "name": {
"type": "String", "type": "String",
"doc": "New profile name. Set to empty string for no profile name", "doc": "New profile name. Set to empty string for no profile name",
"example": "\"signald user\"" "example": "\"signald user\"",
"required": true
}, },
"avatarFile": { "avatarFile": {
"type": "String", "type": "String",
@ -411,12 +430,14 @@
"account": { "account": {
"type": "String", "type": "String",
"doc": "The signal account to use", "doc": "The signal account to use",
"example": "\"+12024561414\"" "example": "\"+12024561414\"",
"required": true
}, },
"partial": { "partial": {
"type": "JsonAddress", "type": "JsonAddress",
"version": "v1", "version": "v1",
"doc": "The partial address, missing fields" "doc": "The partial address, missing fields",
"required": true
} }
}, },
"doc": "Resolve a partial JsonAddress with only a number or UUID to one with both. Anywhere that signald accepts a JsonAddress will except a partial, this is a convenience function for client authors, mostly because signald doesn't resolve all the partials it returns" "doc": "Resolve a partial JsonAddress with only a number or UUID to one with both. Anywhere that signald accepts a JsonAddress will except a partial, this is a convenience function for client authors, mostly because signald doesn't resolve all the partials it returns"
@ -442,27 +463,79 @@
"account": { "account": {
"type": "String", "type": "String",
"doc": "The account to interact with", "doc": "The account to interact with",
"example": "\"+12024561414\"" "example": "\"+12024561414\"",
"required": true
}, },
"to": { "to": {
"type": "JsonAddress", "type": "JsonAddress",
"version": "v1", "version": "v1",
"doc": "The address that sent the message being marked as read" "doc": "The address that sent the message being marked as read",
"required": true
}, },
"timestamps": { "timestamps": {
"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": "1611698481651" "example": "1611966817808",
"required": true
} }
} }
}, },
"GetProfileRequest": {
"fields": {
"account": {
"type": "String",
"doc": "the signald account to use",
"required": true
},
"address": {
"type": "JsonAddress",
"version": "v1",
"doc": "the address to look up",
"required": true
}
},
"doc": "Get all information available about a user"
},
"Profile": {
"fields": {
"name": {
"type": "String",
"doc": "The user's name from local contact names if available, or if not in contact list their Signal profile name"
},
"avatar": {
"type": "String"
},
"address": {
"type": "JsonAddress",
"version": "v1"
},
"capabilities": {
"type": "Capabilities",
"version": "v1"
},
"color": {
"type": "String"
},
"profile_name": {
"type": "String",
"doc": "The user's Signal profile name"
},
"inbox_position": {
"type": "Integer"
},
"expiration_time": {
"type": "int"
}
},
"doc": "Information about a Signal user"
},
"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": "1611698481651" "example": "1611966817808"
}, },
"attachments": { "attachments": {
"list": true, "list": true,
@ -599,7 +672,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": "1611698481651" "example": "1611966817808"
}, },
"author": { "author": {
"type": "JsonAddress", "type": "JsonAddress",
@ -687,7 +760,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": "1611698481651" "example": "1611966817808"
} }
} }
}, },
@ -712,6 +785,19 @@
} }
} }
}, },
"Capabilities": {
"fields": {
"gv2": {
"type": "boolean"
},
"storage": {
"type": "boolean"
},
"gv1-migration": {
"type": "boolean"
}
}
},
"JsonSentTranscriptMessage": { "JsonSentTranscriptMessage": {
"fields": { "fields": {
"destination": { "destination": {
@ -720,7 +806,7 @@
}, },
"timestamp": { "timestamp": {
"type": "long", "type": "long",
"example": "1611698481651" "example": "1611966817808"
}, },
"expirationStartTimestamp": { "expirationStartTimestamp": {
"type": "long" "type": "long"
@ -758,7 +844,7 @@
}, },
"timestamp": { "timestamp": {
"type": "long", "type": "long",
"example": "1611698481651" "example": "1611966817808"
} }
} }
}, },
@ -770,7 +856,7 @@
}, },
"timestamp": { "timestamp": {
"type": "long", "type": "long",
"example": "1611698481651" "example": "1611966817808"
} }
} }
}, },
@ -1200,7 +1286,8 @@
"account": { "account": {
"type": "String", "type": "String",
"doc": "The account to interact with", "doc": "The account to interact with",
"example": "\"+12024561414\"" "example": "\"+12024561414\"",
"required": true
} }
}, },
"doc": "list all linked devices on a Signal account", "doc": "list all linked devices on a Signal account",
@ -1220,12 +1307,14 @@
"account": { "account": {
"type": "String", "type": "String",
"doc": "The account to interact with", "doc": "The account to interact with",
"example": "\"+12024561414\"" "example": "\"+12024561414\"",
"required": true
}, },
"deviceId": { "deviceId": {
"type": "long", "type": "long",
"doc": "the ID of the device to unlink", "doc": "the ID of the device to unlink",
"example": "3" "example": "3",
"required": true
} }
}, },
"doc": "Remove a linked device from the Signal account. Only allowed when the local device id is 1" "doc": "Remove a linked device from the Signal account. Only allowed when the local device id is 1"
@ -1235,12 +1324,14 @@
"account": { "account": {
"type": "String", "type": "String",
"doc": "The account to interact with", "doc": "The account to interact with",
"example": "\"+12024561414\"" "example": "\"+12024561414\"",
"required": true
}, },
"uri": { "uri": {
"type": "String", "type": "String",
"doc": "The signal.group URL", "doc": "The signal.group URL",
"example": "\"https://signal.group/#CjQKINH_GZhXhfifTcnBkaKTNRxW-hHKnGSq-cJNyPVqHRp8EhDUB7zjKNEl0NaULhsqJCX3\"" "example": "\"https://signal.group/#CjQKINH_GZhXhfifTcnBkaKTNRxW-hHKnGSq-cJNyPVqHRp8EhDUB7zjKNEl0NaULhsqJCX3\"",
"required": true
} }
}, },
"doc": "Join a group using the a signal.group URL. Note that you must have a profile name set to join groups.", "doc": "Join a group using the a signal.group URL. Note that you must have a profile name set to join groups.",
@ -1277,11 +1368,13 @@
"account": { "account": {
"type": "String", "type": "String",
"doc": "The account to interact with", "doc": "The account to interact with",
"example": "\"+12024561414\"" "example": "\"+12024561414\"",
"required": true
}, },
"groupID": { "groupID": {
"type": "String", "type": "String",
"example": "\"EdSqI90cS0UomDpgUXOlCoObWvQOXlH5G3Z2d3f4ayE=\"" "example": "\"EdSqI90cS0UomDpgUXOlCoObWvQOXlH5G3Z2d3f4ayE=\"",
"required": true
}, },
"title": { "title": {
"type": "String", "type": "String",
@ -1344,11 +1437,13 @@
"account": { "account": {
"type": "String", "type": "String",
"doc": "The account to interact with", "doc": "The account to interact with",
"example": "\"+12024561414\"" "example": "\"+12024561414\"",
"required": true
}, },
"groupID": { "groupID": {
"type": "String", "type": "String",
"example": "\"EdSqI90cS0UomDpgUXOlCoObWvQOXlH5G3Z2d3f4ayE=\"" "example": "\"EdSqI90cS0UomDpgUXOlCoObWvQOXlH5G3Z2d3f4ayE=\"",
"required": true
} }
}, },
"doc": "Accept a v2 group invitation. Note that you must have a profile name set to join groups.", "doc": "Accept a v2 group invitation. Note that you must have a profile name set to join groups.",
@ -1359,17 +1454,20 @@
"account": { "account": {
"type": "String", "type": "String",
"doc": "The account to interact with", "doc": "The account to interact with",
"example": "\"+12024561414\"" "example": "\"+12024561414\"",
"required": true
}, },
"groupID": { "groupID": {
"type": "String", "type": "String",
"example": "\"EdSqI90cS0UomDpgUXOlCoObWvQOXlH5G3Z2d3f4ayE=\"" "example": "\"EdSqI90cS0UomDpgUXOlCoObWvQOXlH5G3Z2d3f4ayE=\"",
"required": true
}, },
"members": { "members": {
"list": true, "list": true,
"type": "JsonAddress", "type": "JsonAddress",
"version": "v1", "version": "v1",
"doc": "list of requesting members to approve" "doc": "list of requesting members to approve",
"required": true
} }
}, },
"doc": "approve a request to join a group", "doc": "approve a request to join a group",
@ -1380,11 +1478,13 @@
"account": { "account": {
"type": "String", "type": "String",
"doc": "The account to interact with", "doc": "The account to interact with",
"example": "\"+12024561414\"" "example": "\"+12024561414\"",
"required": true
}, },
"groupID": { "groupID": {
"type": "String", "type": "String",
"example": "\"EdSqI90cS0UomDpgUXOlCoObWvQOXlH5G3Z2d3f4ayE=\"" "example": "\"EdSqI90cS0UomDpgUXOlCoObWvQOXlH5G3Z2d3f4ayE=\"",
"required": true
}, },
"revision": { "revision": {
"type": "int", "type": "int",
@ -1401,11 +1501,13 @@
"account": { "account": {
"type": "String", "type": "String",
"doc": "The identifier of the account to interact with", "doc": "The identifier of the account to interact with",
"example": "\"+12024561414\"" "example": "\"+12024561414\"",
"required": true
}, },
"groupID": { "groupID": {
"type": "String", "type": "String",
"example": "\"EdSqI90cS0UomDpgUXOlCoObWvQOXlH5G3Z2d3f4ayE=\"" "example": "\"EdSqI90cS0UomDpgUXOlCoObWvQOXlH5G3Z2d3f4ayE=\"",
"required": true
}, },
"title": { "title": {
"type": "String", "type": "String",
@ -1506,6 +1608,11 @@
}, },
"mark_read": { "mark_read": {
"request": "MarkReadRequest" "request": "MarkReadRequest"
},
"get_profile": {
"request": "GetProfileRequest",
"response": "Profile",
"doc": "Get all information available about a user"
} }
}, },
"v1alpha1": { "v1alpha1": {

View file

@ -143,6 +143,39 @@ func (r *GetLinkedDevicesRequest) Submit(conn *signald.Signald) (response Linked
} }
// Submit: Get all information available about a user
func (r *GetProfileRequest) Submit(conn *signald.Signald) (response Profile, err error) {
r.Version = "v1"
r.Type = "get_profile"
if r.ID == "" {
r.ID = generateID()
}
err = conn.RawRequest(r)
if err != nil {
log.Println("signald-go: error submitting request to signald")
return response, err
}
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 response, err
}
return response, nil
}
// Submit: Join a group using the a signal.group URL. Note that you must have a profile name set to join groups. // Submit: Join a group using the a signal.group URL. Note that you must have a profile name set to join groups.
func (r *JoinGroupRequest) Submit(conn *signald.Signald) (response JsonGroupJoinInfo, err error) { func (r *JoinGroupRequest) Submit(conn *signald.Signald) (response JsonGroupJoinInfo, err error) {
r.Version = "v1" r.Version = "v1"

View file

@ -27,6 +27,12 @@ type ApproveMembershipRequest struct {
Members []*JsonAddress `json:"members,omitempty"` // list of requesting members to approve Members []*JsonAddress `json:"members,omitempty"` // list of requesting members to approve
} }
type Capabilities struct {
Gv1Migration bool `json:"gv1-migration,omitempty"`
Gv2 bool `json:"gv2,omitempty"`
Storage bool `json:"storage,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
@ -41,6 +47,13 @@ type GetLinkedDevicesRequest struct {
Account string `json:"account,omitempty"` // The account to interact with Account string `json:"account,omitempty"` // The account to interact with
} }
// GetProfileRequest: Get all information available about a user
type GetProfileRequest struct {
Request
Account string `json:"account,omitempty"` // the signald account to use
Address *JsonAddress `json:"address,omitempty"` // the address to look up
}
// GroupInfo: A generic type that is used when the group version is not known // GroupInfo: A generic type that is used when the group version is not known
type GroupInfo struct { type GroupInfo struct {
V1 *JsonGroupInfo `json:"v1,omitempty"` V1 *JsonGroupInfo `json:"v1,omitempty"`
@ -229,6 +242,18 @@ type MarkReadRequest struct {
To *JsonAddress `json:"to,omitempty"` // The address that sent the message being marked as read To *JsonAddress `json:"to,omitempty"` // The address that sent the message being marked as read
} }
// Profile: Information about a Signal user
type Profile struct {
Address *JsonAddress `json:"address,omitempty"`
Avatar string `json:"avatar,omitempty"`
Capabilities *Capabilities `json:"capabilities,omitempty"`
Color string `json:"color,omitempty"`
ExpirationTime int32 `json:"expiration_time,omitempty"`
InboxPosition int32 `json:"inbox_position,omitempty"`
Name string `json:"name,omitempty"` // The user's name from local contact names if available, or if not in contact list their Signal profile name
ProfileName string `json:"profile_name,omitempty"` // The user's Signal profile name
}
type ProtocolRequest struct { type ProtocolRequest struct {
Request Request
} }

View file

@ -64,6 +64,10 @@ var fieldNameMap = map[string]string{
"id": "ID", "id": "ID",
"recipientGroupId": "RecipientGroupID", "recipientGroupId": "RecipientGroupID",
"uuid": "UUID", "uuid": "UUID",
"expiration_time": "ExpirationTime",
"inbox_position": "InboxPosition",
"profile_name": "ProfileName",
"gv1-migration": "Gv1Migration",
} }
func (d *DataType) fixForVersion(field, version string) { func (d *DataType) fixForVersion(field, version string) {