Update protocol

This commit is contained in:
Finn 2021-07-01 23:15:11 -07:00
parent 0e612a2e15
commit 8d38d54615
6 changed files with 1274 additions and 46 deletions

File diff suppressed because it is too large Load diff

View file

@ -35,8 +35,3 @@ type LegacyRequest struct {
Captcha string `json:"captcha,omitempty"` Captcha string `json:"captcha,omitempty"`
Version string `json:"version,omitempty"` Version string `json:"version,omitempty"`
} }
type JsonAddress struct {
Number string `json:"number,omitempty" yaml:"number,omitempty"`
UUID string `json:"uuid,omitempty" yaml:"uuid,omitempty"`
}

View file

@ -25,6 +25,19 @@ type ConfigurationMessage struct {
UnidentifiedDeliveryIndicators *Optional `json:"unidentifiedDeliveryIndicators,omitempty" yaml:"unidentifiedDeliveryIndicators,omitempty"` UnidentifiedDeliveryIndicators *Optional `json:"unidentifiedDeliveryIndicators,omitempty" yaml:"unidentifiedDeliveryIndicators,omitempty"`
} }
// GroupAccessControl: group access control settings. Options for each controlled action are: UNKNOWN, ANY, MEMBER, ADMINISTRATOR, UNSATISFIABLE and UNRECOGNIZED
type GroupAccessControl struct {
Attributes string `json:"attributes,omitempty" yaml:"attributes,omitempty"` // who can edit group info
Link string `json:"link,omitempty" yaml:"link,omitempty"` // UNSATISFIABLE when the group link is disabled, ADMINISTRATOR when the group link is enabled but an administrator must approve new members, ANY when the group link is enabled and no approval is required
Members string `json:"members,omitempty" yaml:"members,omitempty"` // who can add members
}
type GroupMember struct {
JoinedRevision int32 `json:"joined_revision,omitempty" yaml:"joined_revision,omitempty"`
Role string `json:"role,omitempty" yaml:"role,omitempty"` // possible values are: UNKNOWN, DEFAULT, ADMINISTRATOR and UNRECOGNIZED
UUID string `json:"uuid,omitempty" yaml:"uuid,omitempty"`
}
type HangupMessage struct { type HangupMessage struct {
DeviceId int32 `json:"deviceId,omitempty" yaml:"deviceId,omitempty"` DeviceId int32 `json:"deviceId,omitempty" yaml:"deviceId,omitempty"`
ID int64 `json:"id,omitempty" yaml:"id,omitempty"` ID int64 `json:"id,omitempty" yaml:"id,omitempty"`
@ -52,6 +65,12 @@ type JsonAccountList struct {
Accounts []*JsonAccount `json:"accounts,omitempty" yaml:"accounts,omitempty"` Accounts []*JsonAccount `json:"accounts,omitempty" yaml:"accounts,omitempty"`
} }
type JsonAddress struct {
Number string `json:"number,omitempty" yaml:"number,omitempty"`
Relay string `json:"relay,omitempty" yaml:"relay,omitempty"`
UUID string `json:"uuid,omitempty" yaml:"uuid,omitempty"`
}
type JsonAttachment struct { type JsonAttachment struct {
Blurhash string `json:"blurhash,omitempty" yaml:"blurhash,omitempty"` Blurhash string `json:"blurhash,omitempty" yaml:"blurhash,omitempty"`
Caption string `json:"caption,omitempty" yaml:"caption,omitempty"` Caption string `json:"caption,omitempty" yaml:"caption,omitempty"`
@ -68,6 +87,11 @@ type JsonAttachment struct {
Width int32 `json:"width,omitempty" yaml:"width,omitempty"` Width int32 `json:"width,omitempty" yaml:"width,omitempty"`
} }
type JsonBlockedListMessage struct {
Addresses []*JsonAddress `json:"addresses,omitempty" yaml:"addresses,omitempty"`
GroupIds []string `json:"groupIds,omitempty" yaml:"groupIds,omitempty"`
}
type JsonCallMessage struct { type JsonCallMessage struct {
AnswerMessage *AnswerMessage `json:"answerMessage,omitempty" yaml:"answerMessage,omitempty"` AnswerMessage *AnswerMessage `json:"answerMessage,omitempty" yaml:"answerMessage,omitempty"`
BusyMessage *BusyMessage `json:"busyMessage,omitempty" yaml:"busyMessage,omitempty"` BusyMessage *BusyMessage `json:"busyMessage,omitempty" yaml:"busyMessage,omitempty"`
@ -78,24 +102,130 @@ type JsonCallMessage struct {
OfferMessage *OfferMessage `json:"offerMessage,omitempty" yaml:"offerMessage,omitempty"` OfferMessage *OfferMessage `json:"offerMessage,omitempty" yaml:"offerMessage,omitempty"`
} }
type JsonDataMessage struct {
Attachments []*JsonAttachment `json:"attachments,omitempty" yaml:"attachments,omitempty"` // files attached to the incoming message
Body string `json:"body,omitempty" yaml:"body,omitempty"` // the text body of the incoming message.
Contacts []*SharedContact `json:"contacts,omitempty" yaml:"contacts,omitempty"` // if the incoming message has a shared contact, the contact's information will be here
EndSession bool `json:"endSession,omitempty" yaml:"endSession,omitempty"`
ExpiresInSeconds int32 `json:"expiresInSeconds,omitempty" yaml:"expiresInSeconds,omitempty"` // the expiry timer on the incoming message. Clients should delete records of the message within this number of seconds
Group *JsonGroupInfo `json:"group,omitempty" yaml:"group,omitempty"` // if the incoming message was sent to a v1 group, information about that group will be here
GroupV2 *JsonGroupV2Info `json:"groupV2,omitempty" yaml:"groupV2,omitempty"` // is the incoming message was sent to a v2 group, basic identifying information about that group will be here. For full information, use list_groups
Mentions []*JsonMention `json:"mentions,omitempty" yaml:"mentions,omitempty"` // list of mentions in the message
Previews []*JsonPreview `json:"previews,omitempty" yaml:"previews,omitempty"` // if the incoming message has a link preview, information about that preview will be here
ProfileKeyUpdate bool `json:"profileKeyUpdate,omitempty" yaml:"profileKeyUpdate,omitempty"`
Quote *JsonQuote `json:"quote,omitempty" yaml:"quote,omitempty"` // if the incoming message is a quote or reply to another message, this will contain information about that message
Reaction *JsonReaction `json:"reaction,omitempty" yaml:"reaction,omitempty"` // if the message adds or removes a reaction to another message, this will indicate what change is being made
RemoteDelete *RemoteDelete `json:"remoteDelete,omitempty" yaml:"remoteDelete,omitempty"` // if the inbound message is deleting a previously sent message, indicates which message should be deleted
Sticker *JsonSticker `json:"sticker,omitempty" yaml:"sticker,omitempty"` // if the incoming message is a sticker, information about the sicker will be here
Timestamp int64 `json:"timestamp,omitempty" yaml:"timestamp,omitempty"` // 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.
ViewOnce bool `json:"viewOnce,omitempty" yaml:"viewOnce,omitempty"` // indicates the message is a view once message. View once messages typically include no body and a single image attachment. Official Signal clients will prevent the user from saving the image, and once the user has viewed the image once they will destroy the image.
}
type JsonGroupInfo struct {
AvatarId int64 `json:"avatarId,omitempty" yaml:"avatarId,omitempty"`
GroupId string `json:"groupId,omitempty" yaml:"groupId,omitempty"`
Members []*JsonAddress `json:"members,omitempty" yaml:"members,omitempty"`
Name string `json:"name,omitempty" yaml:"name,omitempty"`
Type string `json:"type,omitempty" yaml:"type,omitempty"`
}
type JsonGroupV2Info struct {
AccessControl *GroupAccessControl `json:"accessControl,omitempty" yaml:"accessControl,omitempty"` // current access control settings for this group
Avatar string `json:"avatar,omitempty" yaml:"avatar,omitempty"` // path to the group's avatar on local disk, if available
Description string `json:"description,omitempty" yaml:"description,omitempty"`
ID string `json:"id,omitempty" yaml:"id,omitempty"`
InviteLink string `json:"inviteLink,omitempty" yaml:"inviteLink,omitempty"` // the signal.group link, if applicable
MemberDetail []*GroupMember `json:"memberDetail,omitempty" yaml:"memberDetail,omitempty"` // detailed member list
Members []*JsonAddress `json:"members,omitempty" yaml:"members,omitempty"`
PendingMemberDetail []*GroupMember `json:"pendingMemberDetail,omitempty" yaml:"pendingMemberDetail,omitempty"` // detailed pending member list
PendingMembers []*JsonAddress `json:"pendingMembers,omitempty" yaml:"pendingMembers,omitempty"`
RequestingMembers []*JsonAddress `json:"requestingMembers,omitempty" yaml:"requestingMembers,omitempty"`
Revision int32 `json:"revision,omitempty" yaml:"revision,omitempty"`
Timer int32 `json:"timer,omitempty" yaml:"timer,omitempty"`
Title string `json:"title,omitempty" yaml:"title,omitempty"`
}
type JsonMention struct {
Length int32 `json:"length,omitempty" yaml:"length,omitempty"` // The length of the mention represented in the message. Seems to always be 1 but included here in case that changes.
Start int32 `json:"start,omitempty" yaml:"start,omitempty"` // The number of characters in that the mention starts at. Note that due to a quirk of how signald encodes JSON, if this value is 0 (for example if the first character in the message is the mention) the field won't show up.
UUID string `json:"uuid,omitempty" yaml:"uuid,omitempty"` // The UUID of the account being mentioned
}
type JsonMessageEnvelope struct {
CallMessage *JsonCallMessage `json:"callMessage,omitempty" yaml:"callMessage,omitempty"`
DataMessage *JsonDataMessage `json:"dataMessage,omitempty" yaml:"dataMessage,omitempty"`
HasContent bool `json:"hasContent,omitempty" yaml:"hasContent,omitempty"`
HasLegacyMessage bool `json:"hasLegacyMessage,omitempty" yaml:"hasLegacyMessage,omitempty"`
IsUnidentifiedSender bool `json:"isUnidentifiedSender,omitempty" yaml:"isUnidentifiedSender,omitempty"`
Receipt *JsonReceiptMessage `json:"receipt,omitempty" yaml:"receipt,omitempty"`
Relay string `json:"relay,omitempty" yaml:"relay,omitempty"`
ServerDeliveredTimestamp int64 `json:"serverDeliveredTimestamp,omitempty" yaml:"serverDeliveredTimestamp,omitempty"`
ServerTimestamp int64 `json:"serverTimestamp,omitempty" yaml:"serverTimestamp,omitempty"`
Source *JsonAddress `json:"source,omitempty" yaml:"source,omitempty"`
SourceDevice int32 `json:"sourceDevice,omitempty" yaml:"sourceDevice,omitempty"`
SyncMessage *JsonSyncMessage `json:"syncMessage,omitempty" yaml:"syncMessage,omitempty"`
Timestamp int64 `json:"timestamp,omitempty" yaml:"timestamp,omitempty"`
TimestampISO string `json:"timestampISO,omitempty" yaml:"timestampISO,omitempty"`
Type string `json:"type,omitempty" yaml:"type,omitempty"`
Typing *JsonTypingMessage `json:"typing,omitempty" yaml:"typing,omitempty"`
Username string `json:"username,omitempty" yaml:"username,omitempty"`
UUID string `json:"uuid,omitempty" yaml:"uuid,omitempty"`
}
type JsonMessageRequestResponseMessage struct {
GroupId string `json:"groupId,omitempty" yaml:"groupId,omitempty"`
Person *JsonAddress `json:"person,omitempty" yaml:"person,omitempty"`
Type string `json:"type,omitempty" yaml:"type,omitempty"`
}
type JsonPreview struct { type JsonPreview struct {
Attachment *JsonAttachment `json:"attachment,omitempty" yaml:"attachment,omitempty"` Attachment *JsonAttachment `json:"attachment,omitempty" yaml:"attachment,omitempty"`
Title string `json:"title,omitempty" yaml:"title,omitempty"` Title string `json:"title,omitempty" yaml:"title,omitempty"`
Url string `json:"url,omitempty" yaml:"url,omitempty"` Url string `json:"url,omitempty" yaml:"url,omitempty"`
} }
// JsonQuote: A quote is a reply to a previous message. ID is the sent time of the message being replied to
type JsonQuote struct {
Attachments []*JsonQuotedAttachment `json:"attachments,omitempty" yaml:"attachments,omitempty"` // list of files attached to the quoted message
Author *JsonAddress `json:"author,omitempty" yaml:"author,omitempty"` // the author of the message being quoted
ID int64 `json:"id,omitempty" yaml:"id,omitempty"` // the client timestamp of the message being quoted
Mentions []*JsonMention `json:"mentions,omitempty" yaml:"mentions,omitempty"` // list of mentions in the quoted message
Text string `json:"text,omitempty" yaml:"text,omitempty"` // the body of the message being quoted
}
type JsonQuotedAttachment struct { type JsonQuotedAttachment struct {
ContentType string `json:"contentType,omitempty" yaml:"contentType,omitempty"` ContentType string `json:"contentType,omitempty" yaml:"contentType,omitempty"`
FileName string `json:"fileName,omitempty" yaml:"fileName,omitempty"` FileName string `json:"fileName,omitempty" yaml:"fileName,omitempty"`
Thumbnail *JsonAttachment `json:"thumbnail,omitempty" yaml:"thumbnail,omitempty"` Thumbnail *JsonAttachment `json:"thumbnail,omitempty" yaml:"thumbnail,omitempty"`
} }
type JsonReaction struct {
Emoji string `json:"emoji,omitempty" yaml:"emoji,omitempty"` // the emoji to react with
Remove bool `json:"remove,omitempty" yaml:"remove,omitempty"` // set to true to remove the reaction. requires emoji be set to previously reacted emoji
TargetAuthor *JsonAddress `json:"targetAuthor,omitempty" yaml:"targetAuthor,omitempty"` // the author of the message being reacted to
TargetSentTimestamp int64 `json:"targetSentTimestamp,omitempty" yaml:"targetSentTimestamp,omitempty"` // the client timestamp of the message being reacted to
}
type JsonReadMessage struct {
Sender *JsonAddress `json:"sender,omitempty" yaml:"sender,omitempty"`
Timestamp int64 `json:"timestamp,omitempty" yaml:"timestamp,omitempty"`
}
type JsonReceiptMessage struct { type JsonReceiptMessage struct {
Timestamps []int64 `json:"timestamps,omitempty" yaml:"timestamps,omitempty"` Timestamps []int64 `json:"timestamps,omitempty" yaml:"timestamps,omitempty"`
Type string `json:"type,omitempty" yaml:"type,omitempty"` Type string `json:"type,omitempty" yaml:"type,omitempty"`
When int64 `json:"when,omitempty" yaml:"when,omitempty"` When int64 `json:"when,omitempty" yaml:"when,omitempty"`
} }
type JsonSentTranscriptMessage struct {
Destination *JsonAddress `json:"destination,omitempty" yaml:"destination,omitempty"`
ExpirationStartTimestamp int64 `json:"expirationStartTimestamp,omitempty" yaml:"expirationStartTimestamp,omitempty"`
IsRecipientUpdate bool `json:"isRecipientUpdate,omitempty" yaml:"isRecipientUpdate,omitempty"`
Message *JsonDataMessage `json:"message,omitempty" yaml:"message,omitempty"`
Timestamp int64 `json:"timestamp,omitempty" yaml:"timestamp,omitempty"`
UnidentifiedStatus map[string]string `json:"unidentifiedStatus,omitempty" yaml:"unidentifiedStatus,omitempty"`
}
type JsonSticker struct { type JsonSticker struct {
Attachment *JsonAttachment `json:"attachment,omitempty" yaml:"attachment,omitempty"` Attachment *JsonAttachment `json:"attachment,omitempty" yaml:"attachment,omitempty"`
PackID string `json:"packID,omitempty" yaml:"packID,omitempty"` PackID string `json:"packID,omitempty" yaml:"packID,omitempty"`
@ -109,12 +239,40 @@ type JsonStickerPackOperationMessage struct {
Type string `json:"type,omitempty" yaml:"type,omitempty"` Type string `json:"type,omitempty" yaml:"type,omitempty"`
} }
type JsonSyncMessage struct {
BlockedList *JsonBlockedListMessage `json:"blockedList,omitempty" yaml:"blockedList,omitempty"`
Configuration *ConfigurationMessage `json:"configuration,omitempty" yaml:"configuration,omitempty"`
Contacts *JsonAttachment `json:"contacts,omitempty" yaml:"contacts,omitempty"`
ContactsComplete bool `json:"contactsComplete,omitempty" yaml:"contactsComplete,omitempty"`
FetchType string `json:"fetchType,omitempty" yaml:"fetchType,omitempty"`
Groups *JsonAttachment `json:"groups,omitempty" yaml:"groups,omitempty"`
MessageRequestResponse *JsonMessageRequestResponseMessage `json:"messageRequestResponse,omitempty" yaml:"messageRequestResponse,omitempty"`
ReadMessages []*JsonReadMessage `json:"readMessages,omitempty" yaml:"readMessages,omitempty"`
Request string `json:"request,omitempty" yaml:"request,omitempty"`
Sent *JsonSentTranscriptMessage `json:"sent,omitempty" yaml:"sent,omitempty"`
StickerPackOperations []*JsonStickerPackOperationMessage `json:"stickerPackOperations,omitempty" yaml:"stickerPackOperations,omitempty"`
Verified *JsonVerifiedMessage `json:"verified,omitempty" yaml:"verified,omitempty"`
ViewOnceOpen *JsonViewOnceOpenMessage `json:"viewOnceOpen,omitempty" yaml:"viewOnceOpen,omitempty"`
}
type JsonTypingMessage struct { type JsonTypingMessage struct {
Action string `json:"action,omitempty" yaml:"action,omitempty"` Action string `json:"action,omitempty" yaml:"action,omitempty"`
GroupId string `json:"groupId,omitempty" yaml:"groupId,omitempty"` GroupId string `json:"groupId,omitempty" yaml:"groupId,omitempty"`
Timestamp int64 `json:"timestamp,omitempty" yaml:"timestamp,omitempty"` Timestamp int64 `json:"timestamp,omitempty" yaml:"timestamp,omitempty"`
} }
type JsonVerifiedMessage struct {
Destination *JsonAddress `json:"destination,omitempty" yaml:"destination,omitempty"`
IdentityKey string `json:"identityKey,omitempty" yaml:"identityKey,omitempty"`
Timestamp int64 `json:"timestamp,omitempty" yaml:"timestamp,omitempty"`
Verified string `json:"verified,omitempty" yaml:"verified,omitempty"`
}
type JsonViewOnceOpenMessage struct {
Sender *JsonAddress `json:"sender,omitempty" yaml:"sender,omitempty"`
Timestamp int64 `json:"timestamp,omitempty" yaml:"timestamp,omitempty"`
}
type Name struct { type Name struct {
Display *Optional `json:"display,omitempty" yaml:"display,omitempty"` Display *Optional `json:"display,omitempty" yaml:"display,omitempty"`
Family *Optional `json:"family,omitempty" yaml:"family,omitempty"` Family *Optional `json:"family,omitempty" yaml:"family,omitempty"`

View file

@ -160,6 +160,7 @@ func (r *DeleteAccountRequest) Submit(conn *signald.Signald) (err error) {
} }
// Submit: After a linking URI has been requested, finish_link must be called with the session_id provided with the URI. it will return information about the new account once the linking process is completed by the other device.
func (r *FinishLinkRequest) Submit(conn *signald.Signald) (response Account, err error) { func (r *FinishLinkRequest) Submit(conn *signald.Signald) (response Account, err error) {
r.Version = "v1" r.Version = "v1"
r.Type = "finish_link" r.Type = "finish_link"
@ -258,7 +259,7 @@ func (r *GetAllIdentities) Submit(conn *signald.Signald) (response AllIdentityKe
} }
// Submit: Query the server for the latest state of a known group // Submit: Query the server for the latest state of a known group. If no account in signald is a member of the group (anymore), an error with error_type: 'UnknownGroupException' is returned.
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"
r.Type = "get_group" r.Type = "get_group"
@ -676,6 +677,39 @@ func (r *RegisterRequest) Submit(conn *signald.Signald) (response Account, err e
} }
// Submit: delete a message previously sent
func (r *RemoteDeleteRequest) Submit(conn *signald.Signald) (response SendResponse, err error) {
r.Version = "v1"
r.Type = "remote_delete"
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: Remove a linked device from the Signal account. Only allowed when the local device id is 1 // Submit: Remove a linked device from the Signal account. Only allowed when the local device id is 1
func (r *RemoveLinkedDeviceRequest) Submit(conn *signald.Signald) (err error) { func (r *RemoveLinkedDeviceRequest) Submit(conn *signald.Signald) (err error) {
r.Version = "v1" r.Version = "v1"
@ -910,6 +944,32 @@ func (r *SetProfile) Submit(conn *signald.Signald) (err error) {
} }
// Submit: receive incoming messages. After making a subscribe request, incoming messages will be sent to the client encoded as ClientMessageWrapper. Send an unsubscribe request or disconnect from the socket to stop receiving messages.
func (r *SubscribeRequest) Submit(conn *signald.Signald) (err error) {
r.Version = "v1"
r.Type = "subscribe"
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
}
return err
}
// Submit: Trust another user's safety number using either the QR code data or the safety number text // Submit: Trust another user's safety number using either the QR code data or the safety number text
func (r *TrustRequest) Submit(conn *signald.Signald) (err error) { func (r *TrustRequest) Submit(conn *signald.Signald) (err error) {
r.Version = "v1" r.Version = "v1"
@ -962,6 +1022,32 @@ func (r *TypingRequest) Submit(conn *signald.Signald) (err error) {
} }
// Submit: See subscribe for more info
func (r *UnsubscribeRequest) Submit(conn *signald.Signald) (err error) {
r.Version = "v1"
r.Type = "unsubscribe"
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
}
return err
}
// Submit: update information about a local contact // Submit: update information about a local contact
func (r *UpdateContactRequest) Submit(conn *signald.Signald) (response Profile, err error) { func (r *UpdateContactRequest) Submit(conn *signald.Signald) (response Profile, err error) {
r.Version = "v1" r.Version = "v1"

View file

@ -41,6 +41,12 @@ type AllIdentityKeyList struct {
IdentityKeys []*IdentityKeyList `json:"identity_keys,omitempty" yaml:"identity_keys,omitempty"` IdentityKeys []*IdentityKeyList `json:"identity_keys,omitempty" yaml:"identity_keys,omitempty"`
} }
type AnswerMessage struct {
ID int64 `json:"id,omitempty" yaml:"id,omitempty"`
Opaque string `json:"opaque,omitempty" yaml:"opaque,omitempty"`
Sdp string `json:"sdp,omitempty" yaml:"sdp,omitempty"`
}
// ApproveMembershipRequest: approve a request to join a group // ApproveMembershipRequest: approve a request to join a group
type ApproveMembershipRequest struct { type ApproveMembershipRequest struct {
Request Request
@ -49,12 +55,34 @@ type ApproveMembershipRequest struct {
Members []*JsonAddress `json:"members,omitempty" yaml:"members,omitempty"` // list of requesting members to approve Members []*JsonAddress `json:"members,omitempty" yaml:"members,omitempty"` // list of requesting members to approve
} }
type BusyMessage struct {
ID int64 `json:"id,omitempty" yaml:"id,omitempty"`
}
type CallMessage struct {
AnswerMessage *AnswerMessage `json:"answer_message,omitempty" yaml:"answer_message,omitempty"`
BusyMessage *BusyMessage `json:"busy_message,omitempty" yaml:"busy_message,omitempty"`
DestinationDeviceId int32 `json:"destination_device_id,omitempty" yaml:"destination_device_id,omitempty"`
HangupMessage *HangupMessage `json:"hangup_message,omitempty" yaml:"hangup_message,omitempty"`
IceUpdateMessage []*IceUpdateMessage `json:"ice_update_message,omitempty" yaml:"ice_update_message,omitempty"`
MultiRing bool `json:"multi_ring,omitempty" yaml:"multi_ring,omitempty"`
OfferMessage *OfferMessage `json:"offer_message,omitempty" yaml:"offer_message,omitempty"`
}
type Capabilities struct { type Capabilities struct {
Gv1Migration bool `json:"gv1-migration,omitempty" yaml:"gv1-migration,omitempty"` Gv1Migration bool `json:"gv1-migration,omitempty" yaml:"gv1-migration,omitempty"`
Gv2 bool `json:"gv2,omitempty" yaml:"gv2,omitempty"` Gv2 bool `json:"gv2,omitempty" yaml:"gv2,omitempty"`
Storage bool `json:"storage,omitempty" yaml:"storage,omitempty"` Storage bool `json:"storage,omitempty" yaml:"storage,omitempty"`
} }
// ClientMessageWrapper: Wraps all incoming messages after a v1 subscribe request is issued
type ClientMessageWrapper struct {
Data interface{} `json:"data,omitempty" yaml:"data,omitempty"` // the incoming object. The structure will vary from message to message, see `type` and `version` fields
Error bool `json:"error,omitempty" yaml:"error,omitempty"` // true if the incoming message represents an error
Type string `json:"type,omitempty" yaml:"type,omitempty"` // the type of object to expect in the `data` field
Version string `json:"version,omitempty" yaml:"version,omitempty"` // the version of the object in the `data` field
}
type CreateGroupRequest struct { type CreateGroupRequest struct {
Request Request
Account string `json:"account,omitempty" yaml:"account,omitempty"` // The account to interact with Account string `json:"account,omitempty" yaml:"account,omitempty"` // The account to interact with
@ -79,6 +107,7 @@ type DeviceInfo struct {
Name string `json:"name,omitempty" yaml:"name,omitempty"` Name string `json:"name,omitempty" yaml:"name,omitempty"`
} }
// FinishLinkRequest: After a linking URI has been requested, finish_link must be called with the session_id provided with the URI. it will return information about the new account once the linking process is completed by the other device.
type FinishLinkRequest struct { type FinishLinkRequest struct {
Request Request
DeviceName string `json:"device_name,omitempty" yaml:"device_name,omitempty"` DeviceName string `json:"device_name,omitempty" yaml:"device_name,omitempty"`
@ -96,7 +125,7 @@ type GetAllIdentities struct {
Account string `json:"account,omitempty" yaml:"account,omitempty"` // The account to interact with Account string `json:"account,omitempty" yaml:"account,omitempty"` // The account to interact with
} }
// GetGroupRequest: Query the server for the latest state of a known group // GetGroupRequest: Query the server for the latest state of a known group. If no account in signald is a member of the group (anymore), an error with error_type: 'UnknownGroupException' is returned.
type GetGroupRequest struct { type GetGroupRequest struct {
Request Request
Account string `json:"account,omitempty" yaml:"account,omitempty"` // The account to interact with Account string `json:"account,omitempty" yaml:"account,omitempty"` // The account to interact with
@ -122,7 +151,7 @@ type GetProfileRequest struct {
Request Request
Account string `json:"account,omitempty" yaml:"account,omitempty"` // the signald account to use Account string `json:"account,omitempty" yaml:"account,omitempty"` // the signald account to use
Address *JsonAddress `json:"address,omitempty" yaml:"address,omitempty"` // the address to look up Address *JsonAddress `json:"address,omitempty" yaml:"address,omitempty"` // the address to look up
Async bool `json:"async,omitempty" yaml:"async,omitempty"` // return results from local store immediately, refreshing from server if needed. If false (default), block until all pending profiles have been retrieved. Async bool `json:"async,omitempty" yaml:"async,omitempty"` // if true, return results from local store immediately, refreshing from server in the background if needed. if false (default), block until profile can be retrieved from server
} }
// GroupAccessControl: group access control settings. Options for each controlled action are: UNKNOWN, ANY, MEMBER, ADMINISTRATOR, UNSATISFIABLE and UNRECOGNIZED // GroupAccessControl: group access control settings. Options for each controlled action are: UNKNOWN, ANY, MEMBER, ADMINISTRATOR, UNSATISFIABLE and UNRECOGNIZED
@ -156,6 +185,19 @@ type GroupMember struct {
UUID string `json:"uuid,omitempty" yaml:"uuid,omitempty"` UUID string `json:"uuid,omitempty" yaml:"uuid,omitempty"`
} }
type HangupMessage struct {
DeviceId int32 `json:"device_id,omitempty" yaml:"device_id,omitempty"`
ID int64 `json:"id,omitempty" yaml:"id,omitempty"`
Legacy bool `json:"legacy,omitempty" yaml:"legacy,omitempty"`
Type string `json:"type,omitempty" yaml:"type,omitempty"`
}
type IceUpdateMessage struct {
ID int64 `json:"id,omitempty" yaml:"id,omitempty"`
Opaque string `json:"opaque,omitempty" yaml:"opaque,omitempty"`
Sdp string `json:"sdp,omitempty" yaml:"sdp,omitempty"`
}
type IdentityKey struct { type IdentityKey struct {
Added int64 `json:"added,omitempty" yaml:"added,omitempty"` // the first time this identity key was seen Added int64 `json:"added,omitempty" yaml:"added,omitempty"` // the first time this identity key was seen
QrCodeData string `json:"qr_code_data,omitempty" yaml:"qr_code_data,omitempty"` // base64-encoded QR code data QrCodeData string `json:"qr_code_data,omitempty" yaml:"qr_code_data,omitempty"` // base64-encoded QR code data
@ -169,6 +211,25 @@ type IdentityKeyList struct {
Identities []*IdentityKey `json:"identities,omitempty" yaml:"identities,omitempty"` Identities []*IdentityKey `json:"identities,omitempty" yaml:"identities,omitempty"`
} }
type IncomingMessage struct {
Account string `json:"account,omitempty" yaml:"account,omitempty"`
CallMessage *CallMessage `json:"call_message,omitempty" yaml:"call_message,omitempty"`
DataMessage *JsonDataMessage `json:"data_message,omitempty" yaml:"data_message,omitempty"`
HasContent bool `json:"has_content,omitempty" yaml:"has_content,omitempty"`
HasLegacyMessage bool `json:"has_legacy_message,omitempty" yaml:"has_legacy_message,omitempty"`
ReceiptMessage *ReceiptMessage `json:"receipt_message,omitempty" yaml:"receipt_message,omitempty"`
ServerDeliverTimestamp int64 `json:"server_deliver_timestamp,omitempty" yaml:"server_deliver_timestamp,omitempty"`
ServerGuid string `json:"server_guid,omitempty" yaml:"server_guid,omitempty"`
ServerReceiverTimestamp int64 `json:"server_receiver_timestamp,omitempty" yaml:"server_receiver_timestamp,omitempty"`
Source *JsonAddress `json:"source,omitempty" yaml:"source,omitempty"`
SourceDevice int32 `json:"source_device,omitempty" yaml:"source_device,omitempty"`
SyncMessage *JsonSyncMessage `json:"sync_message,omitempty" yaml:"sync_message,omitempty"`
Timestamp int64 `json:"timestamp,omitempty" yaml:"timestamp,omitempty"`
Type string `json:"type,omitempty" yaml:"type,omitempty"`
TypingMessage *TypingMessage `json:"typing_message,omitempty" yaml:"typing_message,omitempty"`
UnidentifiedSender bool `json:"unidentified_sender,omitempty" yaml:"unidentified_sender,omitempty"`
}
// JoinGroupRequest: Join a group using the a signal.group URL. Note that you must have a profile name set to join groups. // JoinGroupRequest: Join a group using the a signal.group URL. Note that you must have a profile name set to join groups.
type JoinGroupRequest struct { type JoinGroupRequest struct {
Request Request
@ -194,18 +255,21 @@ type JsonDataMessage struct {
EndSession bool `json:"endSession,omitempty" yaml:"endSession,omitempty"` EndSession bool `json:"endSession,omitempty" yaml:"endSession,omitempty"`
ExpiresInSeconds int32 `json:"expiresInSeconds,omitempty" yaml:"expiresInSeconds,omitempty"` // the expiry timer on the incoming message. Clients should delete records of the message within this number of seconds ExpiresInSeconds int32 `json:"expiresInSeconds,omitempty" yaml:"expiresInSeconds,omitempty"` // the expiry timer on the incoming message. Clients should delete records of the message within this number of seconds
Group *JsonGroupInfo `json:"group,omitempty" yaml:"group,omitempty"` // if the incoming message was sent to a v1 group, information about that group will be here Group *JsonGroupInfo `json:"group,omitempty" yaml:"group,omitempty"` // if the incoming message was sent to a v1 group, information about that group will be here
GroupV2 *JsonGroupV2Info `json:"groupV2,omitempty" yaml:"groupV2,omitempty"` // is the incoming message was sent to a v2 group, basic identifying information about that group will be here. For full information, use list_groups GroupV2 *JsonGroupV2Info `json:"groupV2,omitempty" yaml:"groupV2,omitempty"` // if the incoming message was sent to a v2 group, basic identifying information about that group will be here. If group information changes, JsonGroupV2Info.revision is incremented. If the group revision is higher than previously seen, a client can retrieve the group information by calling get_group.
GroupCallUpdate string `json:"group_call_update,omitempty" yaml:"group_call_update,omitempty"` // the eraId string from a group call message update
Mentions []*JsonMention `json:"mentions,omitempty" yaml:"mentions,omitempty"` // list of mentions in the message Mentions []*JsonMention `json:"mentions,omitempty" yaml:"mentions,omitempty"` // list of mentions in the message
Payment *Payment `json:"payment,omitempty" yaml:"payment,omitempty"` // details about the MobileCoin payment attached to the message, if present
Previews []*v0.JsonPreview `json:"previews,omitempty" yaml:"previews,omitempty"` // if the incoming message has a link preview, information about that preview will be here Previews []*v0.JsonPreview `json:"previews,omitempty" yaml:"previews,omitempty"` // if the incoming message has a link preview, information about that preview will be here
ProfileKeyUpdate bool `json:"profileKeyUpdate,omitempty" yaml:"profileKeyUpdate,omitempty"` ProfileKeyUpdate bool `json:"profileKeyUpdate,omitempty" yaml:"profileKeyUpdate,omitempty"`
Quote *JsonQuote `json:"quote,omitempty" yaml:"quote,omitempty"` // if the incoming message is a quote or reply to another message, this will contain information about that message Quote *JsonQuote `json:"quote,omitempty" yaml:"quote,omitempty"` // if the incoming message is a quote or reply to another message, this will contain information about that message
Reaction *JsonReaction `json:"reaction,omitempty" yaml:"reaction,omitempty"` // if the message adds or removes a reaction to another message, this will indicate what change is being made Reaction *JsonReaction `json:"reaction,omitempty" yaml:"reaction,omitempty"` // if the message adds or removes a reaction to another message, this will indicate what change is being made
RemoteDelete *v0.RemoteDelete `json:"remoteDelete,omitempty" yaml:"remoteDelete,omitempty"` // if the inbound message is deleting a previously sent message, indicates which message should be deleted RemoteDelete *RemoteDelete `json:"remoteDelete,omitempty" yaml:"remoteDelete,omitempty"` // if the inbound message is deleting a previously sent message, indicates which message should be deleted
Sticker *v0.JsonSticker `json:"sticker,omitempty" yaml:"sticker,omitempty"` // if the incoming message is a sticker, information about the sicker will be here Sticker *v0.JsonSticker `json:"sticker,omitempty" yaml:"sticker,omitempty"` // if the incoming message is a sticker, information about the sicker will be here
Timestamp int64 `json:"timestamp,omitempty" yaml:"timestamp,omitempty"` // 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. Timestamp int64 `json:"timestamp,omitempty" yaml:"timestamp,omitempty"` // 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.
ViewOnce bool `json:"viewOnce,omitempty" yaml:"viewOnce,omitempty"` // indicates the message is a view once message. View once messages typically include no body and a single image attachment. Official Signal clients will prevent the user from saving the image, and once the user has viewed the image once they will destroy the image. ViewOnce bool `json:"viewOnce,omitempty" yaml:"viewOnce,omitempty"` // indicates the message is a view once message. View once messages typically include no body and a single image attachment. Official Signal clients will prevent the user from saving the image, and once the user has viewed the image once they will destroy the image.
} }
// JsonGroupInfo: information about a legacy group
type JsonGroupInfo struct { type JsonGroupInfo struct {
AvatarId int64 `json:"avatarId,omitempty" yaml:"avatarId,omitempty"` AvatarId int64 `json:"avatarId,omitempty" yaml:"avatarId,omitempty"`
GroupId string `json:"groupId,omitempty" yaml:"groupId,omitempty"` GroupId string `json:"groupId,omitempty" yaml:"groupId,omitempty"`
@ -223,6 +287,7 @@ type JsonGroupJoinInfo struct {
Title string `json:"title,omitempty" yaml:"title,omitempty"` Title string `json:"title,omitempty" yaml:"title,omitempty"`
} }
// JsonGroupV2Info: Information about a Signal group
type JsonGroupV2Info struct { type JsonGroupV2Info struct {
AccessControl *GroupAccessControl `json:"accessControl,omitempty" yaml:"accessControl,omitempty"` // current access control settings for this group AccessControl *GroupAccessControl `json:"accessControl,omitempty" yaml:"accessControl,omitempty"` // current access control settings for this group
Avatar string `json:"avatar,omitempty" yaml:"avatar,omitempty"` // path to the group's avatar on local disk, if available Avatar string `json:"avatar,omitempty" yaml:"avatar,omitempty"` // path to the group's avatar on local disk, if available
@ -376,6 +441,11 @@ type ListGroupsRequest struct {
Account string `json:"account,omitempty" yaml:"account,omitempty"` Account string `json:"account,omitempty" yaml:"account,omitempty"`
} }
// ListenerState: indicates when the incoming connection to the signal server has started or stopped
type ListenerState struct {
Connected bool `json:"connected,omitempty" yaml:"connected,omitempty"`
}
type MarkReadRequest struct { type MarkReadRequest struct {
Request Request
Account string `json:"account,omitempty" yaml:"account,omitempty"` // The account to interact with Account string `json:"account,omitempty" yaml:"account,omitempty"` // The account to interact with
@ -384,6 +454,19 @@ type MarkReadRequest struct {
When int64 `json:"when,omitempty" yaml:"when,omitempty"` When int64 `json:"when,omitempty" yaml:"when,omitempty"`
} }
type OfferMessage struct {
ID int64 `json:"id,omitempty" yaml:"id,omitempty"`
Opaque string `json:"opaque,omitempty" yaml:"opaque,omitempty"`
Sdp string `json:"sdp,omitempty" yaml:"sdp,omitempty"`
Type string `json:"type,omitempty" yaml:"type,omitempty"`
}
// Payment: details about a MobileCoin payment
type Payment struct {
Note string `json:"note,omitempty" yaml:"note,omitempty"` // note attached to the payment
Receipt string `json:"receipt,omitempty" yaml:"receipt,omitempty"` // base64 encoded payment receipt data. This is a protobuf value which can be decoded as the Receipt object described in https://github.com/mobilecoinfoundation/mobilecoin/blob/master/api/proto/external.proto
}
// Profile: Information about a Signal user // Profile: Information about a Signal user
type Profile struct { type Profile struct {
About string `json:"about,omitempty" yaml:"about,omitempty"` About string `json:"about,omitempty" yaml:"about,omitempty"`
@ -412,6 +495,12 @@ type ReactRequest struct {
Username string `json:"username,omitempty" yaml:"username,omitempty"` Username string `json:"username,omitempty" yaml:"username,omitempty"`
} }
type ReceiptMessage struct {
Timestamps []int64 `json:"timestamps,omitempty" yaml:"timestamps,omitempty"`
Type string `json:"type,omitempty" yaml:"type,omitempty"` // options: UNKNOWN, DELIVERY, READ, VIEWED
When int64 `json:"when,omitempty" yaml:"when,omitempty"`
}
// RegisterRequest: begin the account registration process by requesting a phone number verification code. when the code is received, submit it with a verify request // RegisterRequest: begin the account registration process by requesting a phone number verification code. when the code is received, submit it with a verify request
type RegisterRequest struct { type RegisterRequest struct {
Request Request
@ -420,6 +509,19 @@ type RegisterRequest struct {
Voice bool `json:"voice,omitempty" yaml:"voice,omitempty"` // set to true to request a voice call instead of an SMS for verification Voice bool `json:"voice,omitempty" yaml:"voice,omitempty"` // set to true to request a voice call instead of an SMS for verification
} }
type RemoteDelete struct {
TargetSentTimestamp int64 `json:"target_sent_timestamp,omitempty" yaml:"target_sent_timestamp,omitempty"`
}
// RemoteDeleteRequest: delete a message previously sent
type RemoteDeleteRequest struct {
Request
Account string `json:"account,omitempty" yaml:"account,omitempty"` // the account to use
Address *JsonAddress `json:"address,omitempty" yaml:"address,omitempty"` // the address to send the delete message to. should match address the message to be deleted was sent to. required if group is not set.
Group string `json:"group,omitempty" yaml:"group,omitempty"` // the group to send the delete message to. should match group the message to be deleted was sent to. required if address is not set.
Timestamp int64 `json:"timestamp,omitempty" yaml:"timestamp,omitempty"`
}
// RemoveLinkedDeviceRequest: Remove a linked device from the Signal account. Only allowed when the local device id is 1 // RemoveLinkedDeviceRequest: Remove a linked device from the Signal account. Only allowed when the local device id is 1
type RemoveLinkedDeviceRequest struct { type RemoveLinkedDeviceRequest struct {
Request Request
@ -494,6 +596,12 @@ type SetProfile struct {
Name string `json:"name,omitempty" yaml:"name,omitempty"` // New profile name. Set to empty string for no profile name Name string `json:"name,omitempty" yaml:"name,omitempty"` // New profile name. Set to empty string for no profile name
} }
// SubscribeRequest: receive incoming messages. After making a subscribe request, incoming messages will be sent to the client encoded as ClientMessageWrapper. Send an unsubscribe request or disconnect from the socket to stop receiving messages.
type SubscribeRequest struct {
Request
Account string `json:"account,omitempty" yaml:"account,omitempty"` // The account to subscribe to incoming message for
}
// TrustRequest: Trust another user's safety number using either the QR code data or the safety number text // TrustRequest: Trust another user's safety number using either the QR code data or the safety number text
type TrustRequest struct { type TrustRequest struct {
Request Request
@ -504,6 +612,12 @@ type TrustRequest struct {
TrustLevel string `json:"trust_level,omitempty" yaml:"trust_level,omitempty"` // One of TRUSTED_UNVERIFIED, TRUSTED_VERIFIED or UNTRUSTED. Default is TRUSTED_VERIFIED TrustLevel string `json:"trust_level,omitempty" yaml:"trust_level,omitempty"` // One of TRUSTED_UNVERIFIED, TRUSTED_VERIFIED or UNTRUSTED. Default is TRUSTED_VERIFIED
} }
type TypingMessage struct {
Action string `json:"action,omitempty" yaml:"action,omitempty"`
GroupId string `json:"group_id,omitempty" yaml:"group_id,omitempty"`
Timestamp int64 `json:"timestamp,omitempty" yaml:"timestamp,omitempty"`
}
// TypingRequest: send a typing started or stopped message // TypingRequest: send a typing started or stopped message
type TypingRequest struct { type TypingRequest struct {
Request Request
@ -514,6 +628,12 @@ type TypingRequest struct {
When int64 `json:"when,omitempty" yaml:"when,omitempty"` When int64 `json:"when,omitempty" yaml:"when,omitempty"`
} }
// UnsubscribeRequest: See subscribe for more info
type UnsubscribeRequest struct {
Request
Account string `json:"account,omitempty" yaml:"account,omitempty"` // The account to unsubscribe from
}
// UpdateContactRequest: update information about a local contact // UpdateContactRequest: update information about a local contact
type UpdateContactRequest struct { type UpdateContactRequest struct {
Request Request

View file

@ -58,6 +58,7 @@ var typeMap = map[string]string{
"boolean": "bool", "boolean": "bool",
"String": "string", "String": "string",
"Map": "map[string]string", // TODO: make signald print the actual key and value types "Map": "map[string]string", // TODO: make signald print the actual key and value types
"Object": "interface{}",
} }
var fieldNameMap = map[string]string{ var fieldNameMap = map[string]string{