bump protocol

This commit is contained in:
finn 2022-02-16 14:52:03 -05:00
parent 219f1df6e5
commit 946b27917d
5 changed files with 1656 additions and 1108 deletions

View file

@ -29,7 +29,6 @@ import (
"gitlab.com/signald/signald-go/cmd/signaldctl/common"
"gitlab.com/signald/signald-go/cmd/signaldctl/config"
v0 "gitlab.com/signald/signald-go/signald/client-protocol/v0"
"gitlab.com/signald/signald-go/signald/client-protocol/v1"
)
@ -67,7 +66,7 @@ var (
req := v1.SendRequest{
Username: account,
MessageBody: strings.Join(args[1:], " "),
Attachments: []*v0.JsonAttachment{},
Attachments: []*v1.JsonAttachment{},
RecipientAddress: toAddress,
RecipientGroupID: toGroup,
}
@ -78,7 +77,7 @@ var (
log.Fatal("error resolving attachment", err)
}
log.Println(path)
req.Attachments = append(req.Attachments, &v0.JsonAttachment{Filename: path})
req.Attachments = append(req.Attachments, &v1.JsonAttachment{Filename: path})
}
resp, err := req.Submit(common.Signald)

File diff suppressed because it is too large Load diff

View file

@ -32,6 +32,20 @@ func mkerr(response client_protocol.BasicResponse) error {
return err
}
return result
case "AttachmentTooLargeError":
result := AttachmentTooLargeError{}
err := json.Unmarshal(response.Error, &result)
if err != nil {
return err
}
return result
case "AuthorizationFailedError":
result := AuthorizationFailedError{}
err := json.Unmarshal(response.Error, &result)
if err != nil {
return err
}
return result
case "CaptchaRequiredError":
result := CaptchaRequiredError{}
err := json.Unmarshal(response.Error, &result)
@ -207,6 +221,13 @@ func mkerr(response client_protocol.BasicResponse) error {
return err
}
return result
case "ScanTimeoutError":
result := ScanTimeoutError{}
err := json.Unmarshal(response.Error, &result)
if err != nil {
return err
}
return result
case "ServerNotFoundError":
result := ServerNotFoundError{}
err := json.Unmarshal(response.Error, &result)
@ -228,6 +249,13 @@ func mkerr(response client_protocol.BasicResponse) error {
return err
}
return result
case "UnregisteredUserError":
result := UnregisteredUserError{}
err := json.Unmarshal(response.Error, &result)
if err != nil {
return err
}
return result
case "UntrustedIdentityError":
result := UntrustedIdentityError{}
err := json.Unmarshal(response.Error, &result)
@ -272,6 +300,24 @@ func (e AccountLockedError) Error() string {
return e.Message
}
type AttachmentTooLargeError struct {
Filename string `json:"filename,omitempty" yaml:"filename,omitempty"`
Message string `json:"message,omitempty" yaml:"message,omitempty"`
}
func (e AttachmentTooLargeError) Error() string {
return e.Message
}
// AuthorizationFailedError: indicates the server rejected our credentials. Typically means the linked device was removed by the primary device, or that the account was re-registered
type AuthorizationFailedError struct {
Message string `json:"message,omitempty" yaml:"message,omitempty"`
}
func (e AuthorizationFailedError) Error() string {
return e.Message
}
type CaptchaRequiredError struct {
Message string `json:"message,omitempty" yaml:"message,omitempty"`
More string `json:"more,omitempty" yaml:"more,omitempty"`
@ -283,6 +329,7 @@ func (e CaptchaRequiredError) Error() string {
type DuplicateMessageError struct {
Message string `json:"message,omitempty" yaml:"message,omitempty"`
Timestamp int64 `json:"timestamp,omitempty" yaml:"timestamp,omitempty"`
}
func (e DuplicateMessageError) Error() string {
@ -470,6 +517,7 @@ type ProtocolInvalidMessageError struct {
Message string `json:"message,omitempty" yaml:"message,omitempty"`
Sender string `json:"sender,omitempty" yaml:"sender,omitempty"`
SenderDevice int32 `json:"sender_device,omitempty" yaml:"sender_device,omitempty"`
Timestamp int64 `json:"timestamp,omitempty" yaml:"timestamp,omitempty"`
}
func (e ProtocolInvalidMessageError) Error() string {
@ -484,6 +532,14 @@ func (e RateLimitError) Error() string {
return e.Message
}
type ScanTimeoutError struct {
Message string `json:"message,omitempty" yaml:"message,omitempty"`
}
func (e ScanTimeoutError) Error() string {
return e.Message
}
type ServerNotFoundError struct {
Message string `json:"message,omitempty" yaml:"message,omitempty"`
UUID string `json:"uuid,omitempty" yaml:"uuid,omitempty"`
@ -509,6 +565,15 @@ func (e UnknownIdentityKeyError) Error() string {
return e.Message
}
type UnregisteredUserError struct {
E164Number string `json:"e164_number,omitempty" yaml:"e164_number,omitempty"`
Message string `json:"message,omitempty" yaml:"message,omitempty"`
}
func (e UnregisteredUserError) Error() string {
return e.Message
}
type UntrustedIdentityError struct {
Identifier string `json:"identifier,omitempty" yaml:"identifier,omitempty"`
IdentityKey **IdentityKey `json:"identity_key,omitempty" yaml:"identity_key,omitempty"`

View file

@ -217,7 +217,7 @@ func (r *RemoveServerRequest) 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.
// 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 and the new account is setup. Note that the account setup process can sometimes take some time, if rapid userfeedback is required after scanning, use wait_for_scan first, then finish setup with finish_link.
func (r *FinishLinkRequest) Submit(conn *signald.Signald) (response Account, err error) {
r.Version = "v1"
r.Type = "finish_link"
@ -316,7 +316,7 @@ func (r *GetAllIdentities) Submit(conn *signald.Signald) (response AllIdentityKe
}
// 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: 'UnknownGroupError' is returned.
// Submit: Query the server for the latest state of a known group. If the account is not a member of the group, an UnknownGroupError is returned.
func (r *GetGroupRequest) Submit(conn *signald.Signald) (response JsonGroupV2Info, err error) {
r.Version = "v1"
r.Type = "get_group"
@ -546,6 +546,39 @@ func (r *GroupLinkInfoRequest) Submit(conn *signald.Signald) (response JsonGroup
}
// Submit: Determine whether an account identifier is registered on the Signal service.
func (r *IsIdentifierRegisteredRequest) Submit(conn *signald.Signald) (response BooleanMessage, err error) {
r.Version = "v1"
r.Type = "is_identifier_registered"
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 = mkerr(rawResponse)
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: 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) {
r.Version = "v1"
@ -1048,7 +1081,7 @@ func (r *SendPaymentRequest) Submit(conn *signald.Signald) (response SendRespons
}
// Submit: set this device's name. This will show up on the mobile device on the same account under
// Submit: set this device's name. This will show up on the mobile device on the same account under settings -> linked devices
func (r *SetDeviceNameRequest) Submit(conn *signald.Signald) (err error) {
r.Version = "v1"
r.Type = "set_device_name"
@ -1391,3 +1424,29 @@ func (r *VersionRequest) Submit(conn *signald.Signald) (response JsonVersionMess
return response, nil
}
// Submit: An optional part of the linking process. Intended to be called after displaying the QR code, will return quickly after the user scans the QR code. finish_link must be called after wait_for_scan returns a non-error
func (r *WaitForScanRequest) Submit(conn *signald.Signald) (err error) {
r.Version = "v1"
r.Type = "wait_for_scan"
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 = mkerr(rawResponse)
return
}
return err
}

View file

@ -62,6 +62,11 @@ type ApproveMembershipRequest struct {
Members []*JsonAddress `json:"members,omitempty" yaml:"members,omitempty"` // list of requesting members to approve
}
// BooleanMessage: A message containing a single boolean, usually as a response
type BooleanMessage struct {
Value bool `json:"value,omitempty" yaml:"value,omitempty"`
}
type BusyMessage struct {
ID int64 `json:"id,omitempty" yaml:"id,omitempty"`
}
@ -77,8 +82,11 @@ type CallMessage struct {
}
type Capabilities struct {
AnnouncementGroup bool `json:"announcement_group,omitempty" yaml:"announcement_group,omitempty"`
ChangeNumber bool `json:"change_number,omitempty" yaml:"change_number,omitempty"`
Gv1Migration bool `json:"gv1-migration,omitempty" yaml:"gv1-migration,omitempty"`
Gv2 bool `json:"gv2,omitempty" yaml:"gv2,omitempty"`
SenderKey bool `json:"sender_key,omitempty" yaml:"sender_key,omitempty"`
Storage bool `json:"storage,omitempty" yaml:"storage,omitempty"`
}
@ -115,7 +123,7 @@ type DeviceInfo struct {
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.
// 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 and the new account is setup. Note that the account setup process can sometimes take some time, if rapid userfeedback is required after scanning, use wait_for_scan first, then finish setup with finish_link.
type FinishLinkRequest struct {
Request
DeviceName string `json:"device_name,omitempty" yaml:"device_name,omitempty"`
@ -134,7 +142,7 @@ type GetAllIdentities struct {
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. If no account in signald is a member of the group (anymore), an error with error_type: 'UnknownGroupError' is returned.
// GetGroupRequest: Query the server for the latest state of a known group. If the account is not a member of the group, an UnknownGroupError is returned.
type GetGroupRequest struct {
Request
Account string `json:"account,omitempty" yaml:"account,omitempty"` // The account to interact with
@ -243,6 +251,13 @@ type IncomingMessage struct {
UnidentifiedSender bool `json:"unidentified_sender,omitempty" yaml:"unidentified_sender,omitempty"`
}
// IsIdentifierRegisteredRequest: Determine whether an account identifier is registered on the Signal service.
type IsIdentifierRegisteredRequest struct {
Request
Account string `json:"account,omitempty" yaml:"account,omitempty"` // The account to use to use
Identifier string `json:"identifier,omitempty" yaml:"identifier,omitempty"` // The UUID of an identifier to check if it is registered on Signal. This UUID is either a Phone Number Identity (PNI) or an Account Identity (ACI).
}
// 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 {
Request
@ -256,7 +271,7 @@ type JsonAddress struct {
UUID string `json:"uuid,omitempty" yaml:"uuid,omitempty"` // A UUID, the unique identifier for a particular Signal account.
}
// JsonAttachment: represents a file attached to a message. When seding, only `filename` is required.
// JsonAttachment: represents a file attached to a message. When sending, only `filename` is required.
type JsonAttachment struct {
Blurhash string `json:"blurhash,omitempty" yaml:"blurhash,omitempty"`
Caption string `json:"caption,omitempty" yaml:"caption,omitempty"`
@ -281,7 +296,7 @@ type JsonBlockedListMessage struct {
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 []*v0.SharedContact `json:"contacts,omitempty" yaml:"contacts,omitempty"` // if the incoming message has a shared contact, the contact's information will be here
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
@ -330,6 +345,7 @@ type JsonGroupV2Info struct {
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"`
Removed bool `json:"removed,omitempty" yaml:"removed,omitempty"` // will be set to true for incoming messages to indicate the user has been removed from the group
RequestingMembers []*JsonAddress `json:"requestingMembers,omitempty" yaml:"requestingMembers,omitempty"`
Revision int32 `json:"revision,omitempty" yaml:"revision,omitempty"`
Timer int32 `json:"timer,omitempty" yaml:"timer,omitempty"`
@ -522,6 +538,7 @@ type Profile struct {
MobilecoinAddress string `json:"mobilecoin_address,omitempty" yaml:"mobilecoin_address,omitempty"` // *base64-encoded* mobilecoin address. Note that this is not the traditional MobileCoin address encoding. Clients are responsible for converting between MobileCoin's custom base58 on the user-facing side and base64 encoding on the signald side. If unset, null or an empty string, will empty the profile payment address
Name string `json:"name,omitempty" yaml:"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" yaml:"profile_name,omitempty"` // The user's Signal profile name
VisibleBadgeIds []string `json:"visible_badge_ids,omitempty" yaml:"visible_badge_ids,omitempty"` // currently unclear how these work, as they are not available in the production Signal apps
}
type ProfileList struct {
@ -612,6 +629,7 @@ type RequestSyncRequest struct {
Configuration bool `json:"configuration,omitempty" yaml:"configuration,omitempty"` // request configuration sync (default true)
Contacts bool `json:"contacts,omitempty" yaml:"contacts,omitempty"` // request contact sync (default true)
Groups bool `json:"groups,omitempty" yaml:"groups,omitempty"` // request group sync (default true)
Keys bool `json:"keys,omitempty" yaml:"keys,omitempty"` // request storage service keys
}
// ResetSessionRequest: reset a session with a particular user
@ -640,7 +658,7 @@ type SendPaymentRequest struct {
type SendRequest struct {
Request
Attachments []*v0.JsonAttachment `json:"attachments,omitempty" yaml:"attachments,omitempty"`
Attachments []*JsonAttachment `json:"attachments,omitempty" yaml:"attachments,omitempty"`
Members []*JsonAddress `json:"members,omitempty" yaml:"members,omitempty"` // Optionally set to a sub-set of group members. Ignored if recipientGroupId isn't specified
Mentions []*JsonMention `json:"mentions,omitempty" yaml:"mentions,omitempty"`
MessageBody string `json:"messageBody,omitempty" yaml:"messageBody,omitempty"`
@ -692,7 +710,7 @@ type ServerList struct {
Servers []*Server `json:"servers,omitempty" yaml:"servers,omitempty"`
}
// SetDeviceNameRequest: set this device's name. This will show up on the mobile device on the same account under
// SetDeviceNameRequest: set this device's name. This will show up on the mobile device on the same account under settings -> linked devices
type SetDeviceNameRequest struct {
Request
Account string `json:"account,omitempty" yaml:"account,omitempty"` // The account to set the device name of
@ -710,12 +728,60 @@ type SetExpirationRequest struct {
type SetProfile struct {
Request
About string `json:"about,omitempty" yaml:"about,omitempty"` // an optional about string. If unset, null or an empty string will unset profile about field
About string `json:"about,omitempty" yaml:"about,omitempty"` // Change the 'about' profile field
Account string `json:"account,omitempty" yaml:"account,omitempty"` // The phone number of the account to use
AvatarFile string `json:"avatarFile,omitempty" yaml:"avatarFile,omitempty"` // Path to new profile avatar file. If unset or null, unset the profile avatar
Emoji string `json:"emoji,omitempty" yaml:"emoji,omitempty"` // an optional single emoji character. If unset, null or an empty string will unset profile emoji
MobilecoinAddress string `json:"mobilecoin_address,omitempty" yaml:"mobilecoin_address,omitempty"` // an optional *base64-encoded* MobileCoin address to set in the profile. Note that this is not the traditional MobileCoin address encoding, which is custom. Clients are responsible for converting between MobileCoin's custom base58 on the user-facing side and base64 encoding on the signald side. If unset, null or an empty string, will empty the profile payment address
Name string `json:"name,omitempty" yaml:"name,omitempty"` // New profile name. Set to empty string for no profile name
Emoji string `json:"emoji,omitempty" yaml:"emoji,omitempty"` // Change the profile emoji
MobilecoinAddress string `json:"mobilecoin_address,omitempty" yaml:"mobilecoin_address,omitempty"` // Change the profile payment address. Payment address must be a *base64-encoded* MobileCoin address. Note that this is not the traditional MobileCoin address encoding, which is custom. Clients are responsible for converting between MobileCoin's custom base58 on the user-facing side and base64 encoding on the signald side.
Name string `json:"name,omitempty" yaml:"name,omitempty"` // Change the profile name
VisibleBadgeIds []string `json:"visible_badge_ids,omitempty" yaml:"visible_badge_ids,omitempty"` // configure visible badge IDs
}
type SharedContact struct {
Address []*SharedContactAddress `json:"address,omitempty" yaml:"address,omitempty"` // the physical addresses of the shared contact
Avatar *SharedContactAvatar `json:"avatar,omitempty" yaml:"avatar,omitempty"` // the profile picture/avatar of the shared contact
Email []*SharedContactEmail `json:"email,omitempty" yaml:"email,omitempty"` // the email addresses of the shared contact
Name *SharedContactName `json:"name,omitempty" yaml:"name,omitempty"` // the name of the shared contact
Organization string `json:"organization,omitempty" yaml:"organization,omitempty"` // the organization (e.g. workplace) of the shared contact
Phone []*SharedContactPhone `json:"phone,omitempty" yaml:"phone,omitempty"` // the phone numbers of the shared contact
}
type SharedContactAddress struct {
City string `json:"city,omitempty" yaml:"city,omitempty"`
Country string `json:"country,omitempty" yaml:"country,omitempty"`
Label string `json:"label,omitempty" yaml:"label,omitempty"`
Neighborhood string `json:"neighborhood,omitempty" yaml:"neighborhood,omitempty"`
Pobox string `json:"pobox,omitempty" yaml:"pobox,omitempty"`
Postcode string `json:"postcode,omitempty" yaml:"postcode,omitempty"`
Region string `json:"region,omitempty" yaml:"region,omitempty"`
Street string `json:"street,omitempty" yaml:"street,omitempty"`
Type string `json:"type,omitempty" yaml:"type,omitempty"` // the type of address (options: HOME, WORK, CUSTOM)
}
type SharedContactAvatar struct {
Attachment *JsonAttachment `json:"attachment,omitempty" yaml:"attachment,omitempty"`
IsProfile bool `json:"is_profile,omitempty" yaml:"is_profile,omitempty"`
}
type SharedContactEmail struct {
Label string `json:"label,omitempty" yaml:"label,omitempty"` // the type label when type is CUSTOM
Type string `json:"type,omitempty" yaml:"type,omitempty"` // the type of email (options: HOME, WORK, MOBILE, CUSTOM)
Value string `json:"value,omitempty" yaml:"value,omitempty"` // the email address
}
type SharedContactName struct {
Display string `json:"display,omitempty" yaml:"display,omitempty"` // the full name that should be displayed
Family string `json:"family,omitempty" yaml:"family,omitempty"` // family name (surname)
Given string `json:"given,omitempty" yaml:"given,omitempty"` // given name
Middle string `json:"middle,omitempty" yaml:"middle,omitempty"` // middle name
Prefix string `json:"prefix,omitempty" yaml:"prefix,omitempty"`
Suffix string `json:"suffix,omitempty" yaml:"suffix,omitempty"`
}
type SharedContactPhone struct {
Label string `json:"label,omitempty" yaml:"label,omitempty"` // the type label when type is CUSTOM
Type string `json:"type,omitempty" yaml:"type,omitempty"` // the type of phone (options: HOME, WORK, MOBILE, CUSTOM)
Value string `json:"value,omitempty" yaml:"value,omitempty"` // the phone number
}
type SubmitChallengeRequest struct {
@ -801,6 +867,12 @@ type VersionRequest struct {
Request
}
// WaitForScanRequest: An optional part of the linking process. Intended to be called after displaying the QR code, will return quickly after the user scans the QR code. finish_link must be called after wait_for_scan returns a non-error
type WaitForScanRequest struct {
Request
SessionId string `json:"session_id,omitempty" yaml:"session_id,omitempty"`
}
// WebSocketConnectionState: indicates when the websocket connection state to the signal server has changed
type WebSocketConnectionState struct {
Socket string `json:"socket,omitempty" yaml:"socket,omitempty"` // One of: UNIDENTIFIED, IDENTIFIED