Update protocol

This commit is contained in:
Finn 2021-02-07 19:59:35 -08:00
parent f315e8d3b6
commit 8c7e571188
3 changed files with 135 additions and 37 deletions

View file

@ -2,9 +2,9 @@
"doc_version": "v1", "doc_version": "v1",
"version": { "version": {
"name": "signald", "name": "signald",
"version": "0.12.0+git2021-01-30rce7ef396.5", "version": "0.12.0+git2021-02-08r98148393.17",
"branch": "main", "branch": "main",
"commit": "ce7ef39669fc7482b2efe6555bc2962cca8e1ca6" "commit": "9814839376b0aceed8329fecc7477a5da7d0cae8"
}, },
"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": "1612005072095" "example": "1612746778552"
}, },
"timestampISO": { "timestampISO": {
"type": "String" "type": "String"
@ -44,7 +44,7 @@
}, },
"serverDeliveredTimestamp": { "serverDeliveredTimestamp": {
"type": "long", "type": "long",
"example": "161200507209580" "example": "161274677855280"
}, },
"hasLegacyMessage": { "hasLegacyMessage": {
"type": "boolean" "type": "boolean"
@ -124,7 +124,7 @@
}, },
"timestamp": { "timestamp": {
"type": "long", "type": "long",
"example": "1612005072095" "example": "1612746778552"
} }
} }
}, },
@ -165,7 +165,7 @@
}, },
"version": { "version": {
"type": "String", "type": "String",
"example": "\"0.12.0+git2021-01-30rce7ef396.5\"" "example": "\"0.12.0+git2021-02-08r98148393.17\""
}, },
"branch": { "branch": {
"type": "String", "type": "String",
@ -173,7 +173,7 @@
}, },
"commit": { "commit": {
"type": "String", "type": "String",
"example": "\"ce7ef39669fc7482b2efe6555bc2962cca8e1ca6\"" "example": "\"9814839376b0aceed8329fecc7477a5da7d0cae8\""
} }
} }
}, },
@ -207,6 +207,11 @@
"type": "String", "type": "String",
"example": "\"Parkdale Run Club\"" "example": "\"Parkdale Run Club\""
}, },
"avatar": {
"type": "String",
"doc": "path to the group's avatar on local disk, if available",
"example": "\"/var/lib/signald/avatars/group-EdSqI90cS0UomDpgUXOlCoObWvQOXlH5G3Z2d3f4ayE=\""
},
"timer": { "timer": {
"type": "int", "type": "int",
"example": "604800" "example": "604800"
@ -227,7 +232,25 @@
"version": "v1" "version": "v1"
}, },
"inviteLink": { "inviteLink": {
"type": "String" "type": "String",
"doc": "the signal.group link, if applicable"
},
"accessControl": {
"type": "GroupAccessControl",
"version": "v1",
"doc": "current access control settings for this group"
},
"memberDetail": {
"list": true,
"type": "GroupMember",
"version": "v1",
"doc": "detailed member list"
},
"pendingMemberDetail": {
"list": true,
"type": "GroupMember",
"version": "v1",
"doc": "detailed pending member list"
} }
} }
}, },
@ -367,6 +390,7 @@
}, },
"groupID": { "groupID": {
"type": "String", "type": "String",
"doc": "the ID of the group to update",
"example": "\"EdSqI90cS0UomDpgUXOlCoObWvQOXlH5G3Z2d3f4ayE=\"", "example": "\"EdSqI90cS0UomDpgUXOlCoObWvQOXlH5G3Z2d3f4ayE=\"",
"required": true "required": true
}, },
@ -378,6 +402,10 @@
"type": "String", "type": "String",
"example": "\"/tmp/image.jpg\"" "example": "\"/tmp/image.jpg\""
}, },
"updateTimer": {
"type": "int",
"doc": "update the group timer."
},
"addMembers": { "addMembers": {
"list": true, "list": true,
"type": "JsonAddress", "type": "JsonAddress",
@ -387,9 +415,22 @@
"list": true, "list": true,
"type": "JsonAddress", "type": "JsonAddress",
"version": "v1" "version": "v1"
},
"updateRole": {
"type": "GroupMember",
"version": "v1"
},
"updateAccessControl": {
"type": "GroupAccessControl",
"version": "v1",
"doc": "note that only one of the access controls may be updated per request"
},
"resetLink": {
"type": "boolean",
"doc": "regenerate the group link password, invalidating the old one"
} }
}, },
"doc": "modify a group" "doc": "modify a group. Note that only one modification action may be preformed at once"
}, },
"GroupInfo": { "GroupInfo": {
"fields": { "fields": {
@ -476,7 +517,7 @@
"list": true, "list": true,
"type": "Long", "type": "Long",
"doc": "List of messages to mark as read", "doc": "List of messages to mark as read",
"example": "1612005072095", "example": "1612746778552",
"required": true "required": true
} }
} }
@ -508,7 +549,8 @@
"doc": "The user's name from local contact names if available, or if not in contact list their Signal profile name" "doc": "The user's name from local contact names if available, or if not in contact list their Signal profile name"
}, },
"avatar": { "avatar": {
"type": "String" "type": "String",
"doc": "path to avatar on local disk"
}, },
"address": { "address": {
"type": "JsonAddress", "type": "JsonAddress",
@ -519,7 +561,8 @@
"version": "v1" "version": "v1"
}, },
"color": { "color": {
"type": "String" "type": "String",
"doc": "color of the chat with this user"
}, },
"profile_name": { "profile_name": {
"type": "String", "type": "String",
@ -582,7 +625,7 @@
"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": "1612005072095" "example": "1612746778552"
}, },
"attachments": { "attachments": {
"list": true, "list": true,
@ -719,7 +762,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": "1612005072095" "example": "1612746778552"
}, },
"author": { "author": {
"type": "JsonAddress", "type": "JsonAddress",
@ -807,7 +850,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": "1612005072095" "example": "1612746778552"
} }
} }
}, },
@ -832,6 +875,40 @@
} }
} }
}, },
"GroupAccessControl": {
"fields": {
"link": {
"type": "String",
"doc": "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",
"example": "\"ANY\""
},
"attributes": {
"type": "String",
"doc": "who can edit group info"
},
"members": {
"type": "String",
"doc": "who can add members"
}
},
"doc": "group access control settings. Options for each controlled action are: UNKNOWN, ANY, MEMBER, ADMINISTRATOR, UNSATISFIABLE and UNRECOGNIZED"
},
"GroupMember": {
"fields": {
"uuid": {
"type": "String",
"example": "\"aeed01f0-a234-478e-8cf7-261c283151e7\""
},
"role": {
"type": "String",
"doc": "possible values are: UNKNOWN, DEFAULT, ADMINISTRATOR and UNRECOGNIZED",
"example": "\"DEFAULT\""
},
"joined_revision": {
"type": "int"
}
}
},
"Capabilities": { "Capabilities": {
"fields": { "fields": {
"gv2": { "gv2": {
@ -853,7 +930,7 @@
}, },
"timestamp": { "timestamp": {
"type": "long", "type": "long",
"example": "1612005072095" "example": "1612746778552"
}, },
"expirationStartTimestamp": { "expirationStartTimestamp": {
"type": "long" "type": "long"
@ -891,7 +968,7 @@
}, },
"timestamp": { "timestamp": {
"type": "long", "type": "long",
"example": "1612005072095" "example": "1612746778552"
} }
} }
}, },
@ -903,7 +980,7 @@
}, },
"timestamp": { "timestamp": {
"type": "long", "type": "long",
"example": "1612005072095" "example": "1612746778552"
} }
} }
}, },
@ -1644,7 +1721,7 @@
"update_group": { "update_group": {
"request": "UpdateGroupRequest", "request": "UpdateGroupRequest",
"response": "GroupInfo", "response": "GroupInfo",
"doc": "modify a group" "doc": "modify a group. Note that only one modification action may be preformed at once"
}, },
"set_profile": { "set_profile": {
"request": "SetProfile" "request": "SetProfile"

View file

@ -471,7 +471,7 @@ func (r *SetProfile) Submit(conn *signald.Signald) (err error) {
} }
// Submit: modify a group // Submit: modify a group. Note that only one modification action may be preformed at once
func (r *UpdateGroupRequest) Submit(conn *signald.Signald) (response GroupInfo, err error) { func (r *UpdateGroupRequest) Submit(conn *signald.Signald) (response GroupInfo, err error) {
r.Version = "v1" r.Version = "v1"
r.Type = "update_group" r.Type = "update_group"

View file

@ -55,6 +55,13 @@ type GetProfileRequest struct {
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"` // return results from local store immediately, refreshing from server if needed. If false (default), block until all pending profiles have been retrieved.
} }
// 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
}
// 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" yaml:"v1,omitempty"` V1 *JsonGroupInfo `json:"v1,omitempty" yaml:"v1,omitempty"`
@ -66,6 +73,12 @@ type GroupList struct {
LegacyGroups []*JsonGroupInfo `json:"legacyGroups,omitempty" yaml:"legacyGroups,omitempty"` LegacyGroups []*JsonGroupInfo `json:"legacyGroups,omitempty" yaml:"legacyGroups,omitempty"`
} }
type GroupMember struct {
Joined_revision 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"`
}
// 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
@ -121,14 +134,18 @@ type JsonGroupJoinInfo struct {
} }
type JsonGroupV2Info struct { type JsonGroupV2Info struct {
ID string `json:"id,omitempty" yaml:"id,omitempty"` AccessControl *GroupAccessControl `json:"accessControl,omitempty" yaml:"accessControl,omitempty"` // current access control settings for this group
InviteLink string `json:"inviteLink,omitempty" yaml:"inviteLink,omitempty"` Avatar string `json:"avatar,omitempty" yaml:"avatar,omitempty"` // path to the group's avatar on local disk, if available
Members []*JsonAddress `json:"members,omitempty" yaml:"members,omitempty"` ID string `json:"id,omitempty" yaml:"id,omitempty"`
PendingMembers []*JsonAddress `json:"pendingMembers,omitempty" yaml:"pendingMembers,omitempty"` InviteLink string `json:"inviteLink,omitempty" yaml:"inviteLink,omitempty"` // the signal.group link, if applicable
RequestingMembers []*JsonAddress `json:"requestingMembers,omitempty" yaml:"requestingMembers,omitempty"` MemberDetail []*GroupMember `json:"memberDetail,omitempty" yaml:"memberDetail,omitempty"` // detailed member list
Revision int32 `json:"revision,omitempty" yaml:"revision,omitempty"` Members []*JsonAddress `json:"members,omitempty" yaml:"members,omitempty"`
Timer int32 `json:"timer,omitempty" yaml:"timer,omitempty"` PendingMemberDetail []*GroupMember `json:"pendingMemberDetail,omitempty" yaml:"pendingMemberDetail,omitempty"` // detailed pending member list
Title string `json:"title,omitempty" yaml:"title,omitempty"` 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 { type JsonMention struct {
@ -262,9 +279,9 @@ type MarkReadRequest struct {
// Profile: Information about a Signal user // Profile: Information about a Signal user
type Profile struct { type Profile struct {
Address *JsonAddress `json:"address,omitempty" yaml:"address,omitempty"` Address *JsonAddress `json:"address,omitempty" yaml:"address,omitempty"`
Avatar string `json:"avatar,omitempty" yaml:"avatar,omitempty"` Avatar string `json:"avatar,omitempty" yaml:"avatar,omitempty"` // path to avatar on local disk
Capabilities *Capabilities `json:"capabilities,omitempty" yaml:"capabilities,omitempty"` Capabilities *Capabilities `json:"capabilities,omitempty" yaml:"capabilities,omitempty"`
Color string `json:"color,omitempty" yaml:"color,omitempty"` Color string `json:"color,omitempty" yaml:"color,omitempty"` // color of the chat with this user
ExpirationTime int32 `json:"expiration_time,omitempty" yaml:"expiration_time,omitempty"` ExpirationTime int32 `json:"expiration_time,omitempty" yaml:"expiration_time,omitempty"`
InboxPosition int32 `json:"inbox_position,omitempty" yaml:"inbox_position,omitempty"` InboxPosition int32 `json:"inbox_position,omitempty" yaml:"inbox_position,omitempty"`
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 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
@ -327,15 +344,19 @@ 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
} }
// UpdateGroupRequest: modify a group // UpdateGroupRequest: modify a group. Note that only one modification action may be preformed at once
type UpdateGroupRequest struct { type UpdateGroupRequest struct {
Request Request
Account string `json:"account,omitempty" yaml:"account,omitempty"` // The identifier of the account to interact with Account string `json:"account,omitempty" yaml:"account,omitempty"` // The identifier of the account to interact with
AddMembers []*JsonAddress `json:"addMembers,omitempty" yaml:"addMembers,omitempty"` AddMembers []*JsonAddress `json:"addMembers,omitempty" yaml:"addMembers,omitempty"`
Avatar string `json:"avatar,omitempty" yaml:"avatar,omitempty"` Avatar string `json:"avatar,omitempty" yaml:"avatar,omitempty"`
GroupID string `json:"groupID,omitempty" yaml:"groupID,omitempty"` GroupID string `json:"groupID,omitempty" yaml:"groupID,omitempty"` // the ID of the group to update
RemoveMembers []*JsonAddress `json:"removeMembers,omitempty" yaml:"removeMembers,omitempty"` RemoveMembers []*JsonAddress `json:"removeMembers,omitempty" yaml:"removeMembers,omitempty"`
Title string `json:"title,omitempty" yaml:"title,omitempty"` ResetLink bool `json:"resetLink,omitempty" yaml:"resetLink,omitempty"` // regenerate the group link password, invalidating the old one
Title string `json:"title,omitempty" yaml:"title,omitempty"`
UpdateAccessControl *GroupAccessControl `json:"updateAccessControl,omitempty" yaml:"updateAccessControl,omitempty"` // note that only one of the access controls may be updated per request
UpdateRole *GroupMember `json:"updateRole,omitempty" yaml:"updateRole,omitempty"`
UpdateTimer int32 `json:"updateTimer,omitempty" yaml:"updateTimer,omitempty"` // update the group timer.
} }
type VersionRequest struct { type VersionRequest struct {