mirror of
https://github.com/mautrix/signal.git
synced 2026-05-15 05:36:53 -04:00
Compare commits
1 commit
main
...
kb/defensi
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
490f5af343 |
63 changed files with 1913 additions and 3456 deletions
14
.github/ISSUE_TEMPLATE/bug.md
vendored
14
.github/ISSUE_TEMPLATE/bug.md
vendored
|
|
@ -7,12 +7,10 @@ type: Bug
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<!-- Include relevant logs, the bridge version and other important details here -->
|
<!--
|
||||||
|
Remember to include relevant logs, the bridge version and any other details.
|
||||||
|
|
||||||
### Checklist
|
It's always best to ask in the Matrix room first, especially if you aren't sure
|
||||||
|
what details are needed. Issues with insufficient detail will likely just be
|
||||||
<!-- All items below are mandatory. Issues not following the rules may be closed without comment. -->
|
ignored or closed immediately.
|
||||||
|
-->
|
||||||
* [ ] This is an actual bug, not just a setup issue (see the [troubleshooting docs](https://docs.mau.fi/bridges/general/troubleshooting.html) or ask in the Matrix room for setup help).
|
|
||||||
* [ ] I am certain that sufficient information is included. Ask in the Matrix room first if not.
|
|
||||||
* [ ] The bug is still present on the main branch. The `!signal version` command output is: ``
|
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,3 @@
|
||||||
# v26.04
|
|
||||||
|
|
||||||
* Updated libsignal to v0.92.1
|
|
||||||
* Added support for admin message deletes from Signal.
|
|
||||||
* Added support for binary service IDs in storage service.
|
|
||||||
* Fixed `private_chat_portal_meta` option not setting DM room names correctly.
|
|
||||||
* Fixed panic if user is logged out during initial chat sync.
|
|
||||||
* Fixed avatar upload failing when creating new Signal group.
|
|
||||||
|
|
||||||
# v26.03
|
# v26.03
|
||||||
|
|
||||||
* Switched to sending binary service ID fields in outgoing messages.
|
* Switched to sending binary service ID fields in outgoing messages.
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
# -- Build libsignal (with Rust) --
|
# -- Build libsignal (with Rust) --
|
||||||
FROM rust:1-alpine AS rust-builder
|
FROM rust:1-alpine AS rust-builder
|
||||||
RUN apk add --no-cache git make cmake protoc musl-dev g++ clang-dev protobuf-dev
|
RUN apk add --no-cache git make cmake protoc musl-dev g++ clang-dev
|
||||||
|
|
||||||
WORKDIR /build
|
WORKDIR /build
|
||||||
# Copy all files needed for Rust build, and no Go files
|
# Copy all files needed for Rust build, and no Go files
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ var m = mxmain.BridgeMain{
|
||||||
Name: "mautrix-signal",
|
Name: "mautrix-signal",
|
||||||
URL: "https://github.com/mautrix/signal",
|
URL: "https://github.com/mautrix/signal",
|
||||||
Description: "A Matrix-Signal puppeting bridge.",
|
Description: "A Matrix-Signal puppeting bridge.",
|
||||||
Version: "26.04",
|
Version: "26.03",
|
||||||
SemCalVer: true,
|
SemCalVer: true,
|
||||||
|
|
||||||
Connector: &connector.SignalConnector{},
|
Connector: &connector.SignalConnector{},
|
||||||
|
|
|
||||||
32
go.mod
32
go.mod
|
|
@ -2,7 +2,7 @@ module go.mau.fi/mautrix-signal
|
||||||
|
|
||||||
go 1.25.0
|
go 1.25.0
|
||||||
|
|
||||||
toolchain go1.26.2
|
toolchain go1.26.1
|
||||||
|
|
||||||
tool go.mau.fi/util/cmd/maubuild
|
tool go.mau.fi/util/cmd/maubuild
|
||||||
|
|
||||||
|
|
@ -11,29 +11,28 @@ require (
|
||||||
github.com/emersion/go-vcard v0.0.0-20241024213814-c9703dde27ff
|
github.com/emersion/go-vcard v0.0.0-20241024213814-c9703dde27ff
|
||||||
github.com/google/uuid v1.6.0
|
github.com/google/uuid v1.6.0
|
||||||
github.com/mattn/go-pointer v0.0.1
|
github.com/mattn/go-pointer v0.0.1
|
||||||
github.com/rs/zerolog v1.35.1
|
github.com/rs/zerolog v1.34.0
|
||||||
github.com/stretchr/testify v1.11.1
|
github.com/stretchr/testify v1.11.1
|
||||||
github.com/tidwall/gjson v1.18.0
|
github.com/tidwall/gjson v1.18.0
|
||||||
go.mau.fi/util v0.9.9-0.20260511124621-9241e81bdf25
|
go.mau.fi/util v0.9.7
|
||||||
golang.org/x/crypto v0.50.0
|
golang.org/x/crypto v0.49.0
|
||||||
golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f
|
golang.org/x/exp v0.0.0-20260312153236-7ab1446f8b90
|
||||||
golang.org/x/net v0.53.0
|
golang.org/x/net v0.52.0
|
||||||
golang.org/x/sync v0.20.0
|
|
||||||
google.golang.org/protobuf v1.36.11
|
google.golang.org/protobuf v1.36.11
|
||||||
gopkg.in/yaml.v3 v3.0.1
|
gopkg.in/yaml.v3 v3.0.1
|
||||||
maunium.net/go/mautrix v0.27.1-0.20260513120123-5fba7e3afae4
|
maunium.net/go/mautrix v0.26.4
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
filippo.io/edwards25519 v1.2.0 // indirect
|
filippo.io/edwards25519 v1.2.0 // indirect
|
||||||
github.com/coreos/go-systemd/v22 v22.7.0 // indirect
|
github.com/coreos/go-systemd/v22 v22.6.0 // indirect
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
github.com/kr/pretty v0.3.1 // indirect
|
github.com/kr/pretty v0.3.1 // indirect
|
||||||
github.com/lib/pq v1.12.3 // indirect
|
github.com/lib/pq v1.11.2 // indirect
|
||||||
github.com/mattn/go-colorable v0.1.14 // indirect
|
github.com/mattn/go-colorable v0.1.14 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
github.com/mattn/go-sqlite3 v1.14.44 // indirect
|
github.com/mattn/go-sqlite3 v1.14.34 // indirect
|
||||||
github.com/petermattis/goid v0.0.0-20260330135022-df67b199bc81 // indirect
|
github.com/petermattis/goid v0.0.0-20260226131333-17d1149c6ac6 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
github.com/rogpeppe/go-internal v1.10.0 // indirect
|
github.com/rogpeppe/go-internal v1.10.0 // indirect
|
||||||
github.com/rs/xid v1.6.0 // indirect
|
github.com/rs/xid v1.6.0 // indirect
|
||||||
|
|
@ -41,11 +40,12 @@ require (
|
||||||
github.com/tidwall/match v1.2.0 // indirect
|
github.com/tidwall/match v1.2.0 // indirect
|
||||||
github.com/tidwall/pretty v1.2.1 // indirect
|
github.com/tidwall/pretty v1.2.1 // indirect
|
||||||
github.com/tidwall/sjson v1.2.5 // indirect
|
github.com/tidwall/sjson v1.2.5 // indirect
|
||||||
github.com/yuin/goldmark v1.8.2 // indirect
|
github.com/yuin/goldmark v1.7.16 // indirect
|
||||||
go.mau.fi/zeroconfig v0.2.0 // indirect
|
go.mau.fi/zeroconfig v0.2.0 // indirect
|
||||||
golang.org/x/mod v0.35.0 // indirect
|
golang.org/x/mod v0.34.0 // indirect
|
||||||
golang.org/x/sys v0.43.0 // indirect
|
golang.org/x/sync v0.20.0 // indirect
|
||||||
golang.org/x/text v0.36.0 // indirect
|
golang.org/x/sys v0.42.0 // indirect
|
||||||
|
golang.org/x/text v0.35.0 // indirect
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
|
||||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
|
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
|
||||||
maunium.net/go/mauflag v1.0.0 // indirect
|
maunium.net/go/mauflag v1.0.0 // indirect
|
||||||
|
|
|
||||||
64
go.sum
64
go.sum
|
|
@ -4,13 +4,15 @@ github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7Oputl
|
||||||
github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU=
|
github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU=
|
||||||
github.com/coder/websocket v1.8.14 h1:9L0p0iKiNOibykf283eHkKUHHrpG7f65OE3BhhO7v9g=
|
github.com/coder/websocket v1.8.14 h1:9L0p0iKiNOibykf283eHkKUHHrpG7f65OE3BhhO7v9g=
|
||||||
github.com/coder/websocket v1.8.14/go.mod h1:NX3SzP+inril6yawo5CQXx8+fk145lPDC6pumgx0mVg=
|
github.com/coder/websocket v1.8.14/go.mod h1:NX3SzP+inril6yawo5CQXx8+fk145lPDC6pumgx0mVg=
|
||||||
github.com/coreos/go-systemd/v22 v22.7.0 h1:LAEzFkke61DFROc7zNLX/WA2i5J8gYqe0rSj9KI28KA=
|
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||||
github.com/coreos/go-systemd/v22 v22.7.0/go.mod h1:xNUYtjHu2EDXbsxz1i41wouACIwT7Ybq9o0BQhMwD0w=
|
github.com/coreos/go-systemd/v22 v22.6.0 h1:aGVa/v8B7hpb0TKl0MWoAavPDmHvobFe5R5zn0bCJWo=
|
||||||
|
github.com/coreos/go-systemd/v22 v22.6.0/go.mod h1:iG+pp635Fo7ZmV/j14KUcmEyWF+0X7Lua8rrTWzYgWU=
|
||||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/emersion/go-vcard v0.0.0-20241024213814-c9703dde27ff h1:4N8wnS3f1hNHSmFD5zgFkWCyA4L1kCDkImPAtK7D6tg=
|
github.com/emersion/go-vcard v0.0.0-20241024213814-c9703dde27ff h1:4N8wnS3f1hNHSmFD5zgFkWCyA4L1kCDkImPAtK7D6tg=
|
||||||
github.com/emersion/go-vcard v0.0.0-20241024213814-c9703dde27ff/go.mod h1:HMJKR5wlh/ziNp+sHEDV2ltblO4JD2+IdDOWtGcQBTM=
|
github.com/emersion/go-vcard v0.0.0-20241024213814-c9703dde27ff/go.mod h1:HMJKR5wlh/ziNp+sHEDV2ltblO4JD2+IdDOWtGcQBTM=
|
||||||
|
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||||
|
|
@ -22,19 +24,23 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||||
github.com/lib/pq v1.12.3 h1:tTWxr2YLKwIvK90ZXEw8GP7UFHtcbTtty8zsI+YjrfQ=
|
github.com/lib/pq v1.11.2 h1:x6gxUeu39V0BHZiugWe8LXZYZ+Utk7hSJGThs8sdzfs=
|
||||||
github.com/lib/pq v1.12.3/go.mod h1:/p+8NSbOcwzAEI7wiMXFlgydTwcgTr3OSKMsD2BitpA=
|
github.com/lib/pq v1.11.2/go.mod h1:/p+8NSbOcwzAEI7wiMXFlgydTwcgTr3OSKMsD2BitpA=
|
||||||
|
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||||
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
|
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
|
||||||
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
|
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
|
||||||
|
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||||
|
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||||
github.com/mattn/go-pointer v0.0.1 h1:n+XhsuGeVO6MEAp7xyEukFINEa+Quek5psIR/ylA6o0=
|
github.com/mattn/go-pointer v0.0.1 h1:n+XhsuGeVO6MEAp7xyEukFINEa+Quek5psIR/ylA6o0=
|
||||||
github.com/mattn/go-pointer v0.0.1/go.mod h1:2zXcozF6qYGgmsG+SeTZz3oAbFLdD3OWqnUbNvJZAlc=
|
github.com/mattn/go-pointer v0.0.1/go.mod h1:2zXcozF6qYGgmsG+SeTZz3oAbFLdD3OWqnUbNvJZAlc=
|
||||||
github.com/mattn/go-sqlite3 v1.14.44 h1:3VSe+xafpbzsLbdr2AWlAZk9yRHiBhTBakioXaCKTF8=
|
github.com/mattn/go-sqlite3 v1.14.34 h1:3NtcvcUnFBPsuRcno8pUtupspG/GM+9nZ88zgJcp6Zk=
|
||||||
github.com/mattn/go-sqlite3 v1.14.44/go.mod h1:pjEuOr8IwzLJP2MfGeTb0A35jauH+C2kbHKBr7yXKVQ=
|
github.com/mattn/go-sqlite3 v1.14.34/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||||
github.com/petermattis/goid v0.0.0-20260330135022-df67b199bc81 h1:WDsQxOJDy0N1VRAjXLpi8sCEZRSGarLWQevDxpTBRrM=
|
github.com/petermattis/goid v0.0.0-20260226131333-17d1149c6ac6 h1:rh2lKw/P/EqHa724vYH2+VVQ1YnW4u6EOXl0PMAovZE=
|
||||||
github.com/petermattis/goid v0.0.0-20260330135022-df67b199bc81/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4=
|
github.com/petermattis/goid v0.0.0-20260226131333-17d1149c6ac6/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4=
|
||||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||||
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||||
|
|
@ -42,8 +48,8 @@ github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjR
|
||||||
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
|
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
|
||||||
github.com/rs/xid v1.6.0 h1:fV591PaemRlL6JfRxGDEPl69wICngIQ3shQtzfy2gxU=
|
github.com/rs/xid v1.6.0 h1:fV591PaemRlL6JfRxGDEPl69wICngIQ3shQtzfy2gxU=
|
||||||
github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0=
|
github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0=
|
||||||
github.com/rs/zerolog v1.35.1 h1:m7xQeoiLIiV0BCEY4Hs+j2NG4Gp2o2KPKmhnnLiazKI=
|
github.com/rs/zerolog v1.34.0 h1:k43nTLIwcTVQAncfCw4KZ2VY6ukYoZaBPNOE8txlOeY=
|
||||||
github.com/rs/zerolog v1.35.1/go.mod h1:EjML9kdfa/RMA7h/6z6pYmq1ykOuA8/mjWaEvGI+jcw=
|
github.com/rs/zerolog v1.34.0/go.mod h1:bJsvje4Z08ROH4Nhs5iH600c3IkWhwp44iRc54W6wYQ=
|
||||||
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0=
|
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0=
|
||||||
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M=
|
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M=
|
||||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||||
|
|
@ -59,27 +65,29 @@ github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4=
|
||||||
github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
||||||
github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY=
|
github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY=
|
||||||
github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28=
|
github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28=
|
||||||
github.com/yuin/goldmark v1.8.2 h1:kEGpgqJXdgbkhcOgBxkC0X0PmoPG1ZyoZ117rDVp4zE=
|
github.com/yuin/goldmark v1.7.16 h1:n+CJdUxaFMiDUNnWC3dMWCIQJSkxH4uz3ZwQBkAlVNE=
|
||||||
github.com/yuin/goldmark v1.8.2/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg=
|
github.com/yuin/goldmark v1.7.16/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg=
|
||||||
go.mau.fi/util v0.9.9-0.20260511124621-9241e81bdf25 h1:YPEmc+li7TF6C9AdRTcSLMb6yCHdF27/wNT7kFLIVNg=
|
go.mau.fi/util v0.9.7 h1:AWGNbJfz1zRcQOKeOEYhKUG2fT+/26Gy6kyqcH8tnBg=
|
||||||
go.mau.fi/util v0.9.9-0.20260511124621-9241e81bdf25/go.mod h1:jE9FfhbgEgAwxei6lomO9v8zdCIATcquONUu4vjRwSs=
|
go.mau.fi/util v0.9.7/go.mod h1:5T2f3ZWZFAGgmFwg3dGw7YK6kIsb9lryDzvynoR98pE=
|
||||||
go.mau.fi/zeroconfig v0.2.0 h1:e/OGEERqVRRKlgaro7E6bh8xXiKFSXB3eNNIud7FUjU=
|
go.mau.fi/zeroconfig v0.2.0 h1:e/OGEERqVRRKlgaro7E6bh8xXiKFSXB3eNNIud7FUjU=
|
||||||
go.mau.fi/zeroconfig v0.2.0/go.mod h1:J0Vn0prHNOm493oZoQ84kq83ZaNCYZnq+noI1b1eN8w=
|
go.mau.fi/zeroconfig v0.2.0/go.mod h1:J0Vn0prHNOm493oZoQ84kq83ZaNCYZnq+noI1b1eN8w=
|
||||||
golang.org/x/crypto v0.50.0 h1:zO47/JPrL6vsNkINmLoo/PH1gcxpls50DNogFvB5ZGI=
|
golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4=
|
||||||
golang.org/x/crypto v0.50.0/go.mod h1:3muZ7vA7PBCE6xgPX7nkzzjiUq87kRItoJQM1Yo8S+Q=
|
golang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA=
|
||||||
golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f h1:W3F4c+6OLc6H2lb//N1q4WpJkhzJCK5J6kUi1NTVXfM=
|
golang.org/x/exp v0.0.0-20260312153236-7ab1446f8b90 h1:jiDhWWeC7jfWqR9c/uplMOqJ0sbNlNWv0UkzE0vX1MA=
|
||||||
golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f/go.mod h1:J1xhfL/vlindoeF/aINzNzt2Bket5bjo9sdOYzOsU80=
|
golang.org/x/exp v0.0.0-20260312153236-7ab1446f8b90/go.mod h1:xE1HEv6b+1SCZ5/uscMRjUBKtIxworgEcEi+/n9NQDQ=
|
||||||
golang.org/x/mod v0.35.0 h1:Ww1D637e6Pg+Zb2KrWfHQUnH2dQRLBQyAtpr/haaJeM=
|
golang.org/x/mod v0.34.0 h1:xIHgNUUnW6sYkcM5Jleh05DvLOtwc6RitGHbDk4akRI=
|
||||||
golang.org/x/mod v0.35.0/go.mod h1:+GwiRhIInF8wPm+4AoT6L0FA1QWAad3OMdTRx4tFYlU=
|
golang.org/x/mod v0.34.0/go.mod h1:ykgH52iCZe79kzLLMhyCUzhMci+nQj+0XkbXpNYtVjY=
|
||||||
golang.org/x/net v0.53.0 h1:d+qAbo5L0orcWAr0a9JweQpjXF19LMXJE8Ey7hwOdUA=
|
golang.org/x/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0=
|
||||||
golang.org/x/net v0.53.0/go.mod h1:JvMuJH7rrdiCfbeHoo3fCQU24Lf5JJwT9W3sJFulfgs=
|
golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw=
|
||||||
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
|
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
|
||||||
golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
|
golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
|
||||||
|
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI=
|
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo=
|
||||||
golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg=
|
golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
||||||
golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164=
|
golang.org/x/text v0.35.0 h1:JOVx6vVDFokkpaq1AEptVzLTpDe9KGpj5tR4/X+ybL8=
|
||||||
|
golang.org/x/text v0.35.0/go.mod h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA=
|
||||||
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
|
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
|
||||||
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
|
@ -91,5 +99,5 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
maunium.net/go/mauflag v1.0.0 h1:YiaRc0tEI3toYtJMRIfjP+jklH45uDHtT80nUamyD4M=
|
maunium.net/go/mauflag v1.0.0 h1:YiaRc0tEI3toYtJMRIfjP+jklH45uDHtT80nUamyD4M=
|
||||||
maunium.net/go/mauflag v1.0.0/go.mod h1:nLivPOpTpHnpzEh8jEdSL9UqO9+/KBJFmNRlwKfkPeA=
|
maunium.net/go/mauflag v1.0.0/go.mod h1:nLivPOpTpHnpzEh8jEdSL9UqO9+/KBJFmNRlwKfkPeA=
|
||||||
maunium.net/go/mautrix v0.27.1-0.20260513120123-5fba7e3afae4 h1:zNC9eVAhw8FhKpM3AxNAh/iy75UEYX91uJUvqqAYlvo=
|
maunium.net/go/mautrix v0.26.4 h1:enHSnkf0L2V9+VnfJfNhKSReSW6pBKS/x3Su+v+Vovs=
|
||||||
maunium.net/go/mautrix v0.27.1-0.20260513120123-5fba7e3afae4/go.mod h1:3sOGhXi3P1V6/NruTA0gujkvTypXVUraWktCuTGyDuM=
|
maunium.net/go/mautrix v0.26.4/go.mod h1:YWw8NWTszsbyFAznboicBObwHPgTSLcuTbVX2kY7U2M=
|
||||||
|
|
|
||||||
|
|
@ -187,7 +187,7 @@ func (s *SignalClient) FetchMessages(ctx context.Context, params bridgev2.FetchM
|
||||||
CompleteCallback: func() {
|
CompleteCallback: func() {
|
||||||
// When reaching the last backwards backfill batch, delete the chat from the backup store.
|
// When reaching the last backwards backfill batch, delete the chat from the backup store.
|
||||||
// If backwards backfilling isn't enabled, delete immediately after the first backfill request.
|
// If backwards backfilling isn't enabled, delete immediately after the first backfill request.
|
||||||
if (!params.Forward && len(items) < params.Count) || !s.Main.Bridge.Config.Backfill.Queue.AnyEnabled() {
|
if (!params.Forward && len(items) < params.Count) || (!s.Main.Bridge.Config.Backfill.Queue.Enabled && !s.Main.Bridge.Config.Backfill.WillPaginateManually) {
|
||||||
err := s.Client.Store.BackupStore.DeleteBackupChat(ctx, chat.Id)
|
err := s.Client.Store.BackupStore.DeleteBackupChat(ctx, chat.Id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
zerolog.Ctx(ctx).Err(err).Msg("Failed to delete chat from backup store")
|
zerolog.Ctx(ctx).Err(err).Msg("Failed to delete chat from backup store")
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ func supportedIfFFmpeg() event.CapabilitySupportLevel {
|
||||||
}
|
}
|
||||||
|
|
||||||
func capID() string {
|
func capID() string {
|
||||||
base := "fi.mau.signal.capabilities.2026_05_12"
|
base := "fi.mau.signal.capabilities.2025_12_09"
|
||||||
if ffmpeg.Supported() {
|
if ffmpeg.Supported() {
|
||||||
return base + "+ffmpeg"
|
return base + "+ffmpeg"
|
||||||
}
|
}
|
||||||
|
|
@ -111,8 +111,7 @@ var signalCaps = &event.RoomFeatures{
|
||||||
},
|
},
|
||||||
event.CapMsgSticker: {
|
event.CapMsgSticker: {
|
||||||
MimeTypes: map[string]event.CapabilitySupportLevel{
|
MimeTypes: map[string]event.CapabilitySupportLevel{
|
||||||
// Signal clients will only render static webp, so apng is preferred
|
"image/webp": event.CapLevelFullySupported,
|
||||||
"image/webp": event.CapLevelPartialSupport,
|
|
||||||
"image/png": event.CapLevelFullySupported,
|
"image/png": event.CapLevelFullySupported,
|
||||||
"image/apng": event.CapLevelFullySupported,
|
"image/apng": event.CapLevelFullySupported,
|
||||||
"image/gif": supportedIfFFmpeg(),
|
"image/gif": supportedIfFFmpeg(),
|
||||||
|
|
@ -212,7 +211,6 @@ var signalGeneralCaps = &bridgev2.NetworkGeneralCapabilities{
|
||||||
AggressiveUpdateInfo: true,
|
AggressiveUpdateInfo: true,
|
||||||
ImplicitReadReceipts: true,
|
ImplicitReadReceipts: true,
|
||||||
Provisioning: bridgev2.ProvisioningCapabilities{
|
Provisioning: bridgev2.ProvisioningCapabilities{
|
||||||
ImagePackImport: true,
|
|
||||||
ResolveIdentifier: bridgev2.ResolveIdentifierCapabilities{
|
ResolveIdentifier: bridgev2.ResolveIdentifierCapabilities{
|
||||||
CreateDM: true,
|
CreateDM: true,
|
||||||
LookupPhone: true,
|
LookupPhone: true,
|
||||||
|
|
@ -237,5 +235,5 @@ func (s *SignalConnector) GetCapabilities() *bridgev2.NetworkGeneralCapabilities
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SignalConnector) GetBridgeInfoVersion() (info, capabilities int) {
|
func (s *SignalConnector) GetBridgeInfoVersion() (info, capabilities int) {
|
||||||
return 1, 8
|
return 1, 7
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -332,7 +332,7 @@ func (s *SignalClient) CreateGroup(ctx context.Context, params *bridgev2.GroupCr
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to download avatar: %w", err)
|
return nil, fmt.Errorf("failed to download avatar: %w", err)
|
||||||
}
|
}
|
||||||
group.AvatarPath, err = s.Client.UploadGroupAvatar(ctx, avatarBytes, group.GroupIdentifier, group.GroupMasterKey)
|
group.AvatarPath, err = s.Client.UploadGroupAvatar(ctx, avatarBytes, group.GroupIdentifier)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to upload avatar: %w", err)
|
return nil, fmt.Errorf("failed to upload avatar: %w", err)
|
||||||
}
|
}
|
||||||
|
|
@ -362,7 +362,7 @@ func (s *SignalClient) CreateGroup(ctx context.Context, params *bridgev2.GroupCr
|
||||||
return nil, fmt.Errorf("failed to set portal room ID: %w", err)
|
return nil, fmt.Errorf("failed to set portal room ID: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
resp, err := s.Client.CreateGroup(ctx, group)
|
resp, err := s.Client.CreateGroup(ctx, group, avatarBytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to create group: %w", err)
|
return nil, fmt.Errorf("failed to create group: %w", err)
|
||||||
}
|
}
|
||||||
|
|
@ -414,7 +414,7 @@ func (s *SignalClient) GetContactList(ctx context.Context) ([]*bridgev2.ResolveI
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SignalClient) makeCreateDMResponse(ctx context.Context, recipient *types.Recipient, backupChat *store.BackupChat) *bridgev2.CreateChatResponse {
|
func (s *SignalClient) makeCreateDMResponse(ctx context.Context, recipient *types.Recipient, backupChat *store.BackupChat) *bridgev2.CreateChatResponse {
|
||||||
namePtr := bridgev2.DefaultChatName
|
name := ""
|
||||||
topic := PrivateChatTopic
|
topic := PrivateChatTopic
|
||||||
selfUser := s.makeEventSender(s.Client.Store.ACI)
|
selfUser := s.makeEventSender(s.Client.Store.ACI)
|
||||||
members := &bridgev2.ChatMemberList{
|
members := &bridgev2.ChatMemberList{
|
||||||
|
|
@ -441,7 +441,7 @@ func (s *SignalClient) makeCreateDMResponse(ctx context.Context, recipient *type
|
||||||
var serviceID libsignalgo.ServiceID
|
var serviceID libsignalgo.ServiceID
|
||||||
var avatar *bridgev2.Avatar
|
var avatar *bridgev2.Avatar
|
||||||
if recipient.ACI == uuid.Nil {
|
if recipient.ACI == uuid.Nil {
|
||||||
namePtr = ptr.Ptr(s.Main.Config.FormatDisplayname(recipient))
|
name = s.Main.Config.FormatDisplayname(recipient)
|
||||||
serviceID = libsignalgo.NewPNIServiceID(recipient.PNI)
|
serviceID = libsignalgo.NewPNIServiceID(recipient.PNI)
|
||||||
} else {
|
} else {
|
||||||
if backupChat == nil {
|
if backupChat == nil {
|
||||||
|
|
@ -453,7 +453,7 @@ func (s *SignalClient) makeCreateDMResponse(ctx context.Context, recipient *type
|
||||||
}
|
}
|
||||||
members.OtherUserID = signalid.MakeUserID(recipient.ACI)
|
members.OtherUserID = signalid.MakeUserID(recipient.ACI)
|
||||||
if recipient.ACI == s.Client.Store.ACI {
|
if recipient.ACI == s.Client.Store.ACI {
|
||||||
namePtr = ptr.Ptr(NoteToSelfName)
|
name = NoteToSelfName
|
||||||
avatar = &bridgev2.Avatar{
|
avatar = &bridgev2.Avatar{
|
||||||
ID: networkid.AvatarID(s.Main.Config.NoteToSelfAvatar),
|
ID: networkid.AvatarID(s.Main.Config.NoteToSelfAvatar),
|
||||||
Remove: len(s.Main.Config.NoteToSelfAvatar) == 0,
|
Remove: len(s.Main.Config.NoteToSelfAvatar) == 0,
|
||||||
|
|
@ -474,7 +474,7 @@ func (s *SignalClient) makeCreateDMResponse(ctx context.Context, recipient *type
|
||||||
return &bridgev2.CreateChatResponse{
|
return &bridgev2.CreateChatResponse{
|
||||||
PortalKey: s.makeDMPortalKey(serviceID),
|
PortalKey: s.makeDMPortalKey(serviceID),
|
||||||
PortalInfo: &bridgev2.ChatInfo{
|
PortalInfo: &bridgev2.ChatInfo{
|
||||||
Name: namePtr,
|
Name: &name,
|
||||||
Avatar: avatar,
|
Avatar: avatar,
|
||||||
Topic: &topic,
|
Topic: &topic,
|
||||||
Members: members,
|
Members: members,
|
||||||
|
|
|
||||||
|
|
@ -32,19 +32,10 @@ import (
|
||||||
"go.mau.fi/mautrix-signal/pkg/signalmeow/types"
|
"go.mau.fi/mautrix-signal/pkg/signalmeow/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *SignalClient) stopChatSync() {
|
func (s *SignalClient) syncChats(ctx context.Context) {
|
||||||
if cancel := s.cancelChatSync.Swap(nil); cancel != nil {
|
|
||||||
(*cancel)()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *SignalClient) syncChats(ctx context.Context, cancel context.CancelFunc) {
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
if s.UserLogin.Metadata.(*signalid.UserLoginMetadata).ChatsSynced {
|
if s.UserLogin.Metadata.(*signalid.UserLoginMetadata).ChatsSynced {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.Client.Store.EphemeralBackupKey != nil {
|
if s.Client.Store.EphemeralBackupKey != nil {
|
||||||
zerolog.Ctx(ctx).Info().Msg("Fetching transfer archive before syncing chats")
|
zerolog.Ctx(ctx).Info().Msg("Fetching transfer archive before syncing chats")
|
||||||
meta, err := s.Client.WaitForTransfer(ctx)
|
meta, err := s.Client.WaitForTransfer(ctx)
|
||||||
|
|
@ -74,22 +65,10 @@ func (s *SignalClient) syncChats(ctx context.Context, cancel context.CancelFunc)
|
||||||
}
|
}
|
||||||
zerolog.Ctx(ctx).Info().Int("chat_count", len(chats)).Msg("Fetched chats to sync from database")
|
zerolog.Ctx(ctx).Info().Int("chat_count", len(chats)).Msg("Fetched chats to sync from database")
|
||||||
for _, chat := range chats {
|
for _, chat := range chats {
|
||||||
if ctx.Err() != nil {
|
|
||||||
zerolog.Ctx(ctx).Debug().
|
|
||||||
AnErr("ctx_err", ctx.Err()).
|
|
||||||
Msg("Context cancelled while syncing chats, stopping")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
recipient, err := s.Client.Store.BackupStore.GetBackupRecipient(ctx, chat.RecipientId)
|
recipient, err := s.Client.Store.BackupStore.GetBackupRecipient(ctx, chat.RecipientId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
zerolog.Ctx(ctx).Err(err).Msg("Failed to get recipient for chat")
|
zerolog.Ctx(ctx).Err(err).Msg("Failed to get recipient for chat")
|
||||||
continue
|
continue
|
||||||
} else if recipient == nil {
|
|
||||||
zerolog.Ctx(ctx).Warn().
|
|
||||||
Uint64("backup_chat_id", chat.Id).
|
|
||||||
Uint64("backup_recipient_id", chat.RecipientId).
|
|
||||||
Msg("No recipient found for chat")
|
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
resyncEvt := &simplevent.ChatResync{
|
resyncEvt := &simplevent.ChatResync{
|
||||||
EventMeta: simplevent.EventMeta{
|
EventMeta: simplevent.EventMeta{
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,6 @@ package connector
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"sync/atomic"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
|
|
@ -27,7 +26,6 @@ import (
|
||||||
"maunium.net/go/mautrix/bridgev2"
|
"maunium.net/go/mautrix/bridgev2"
|
||||||
"maunium.net/go/mautrix/bridgev2/networkid"
|
"maunium.net/go/mautrix/bridgev2/networkid"
|
||||||
"maunium.net/go/mautrix/bridgev2/status"
|
"maunium.net/go/mautrix/bridgev2/status"
|
||||||
"maunium.net/go/mautrix/event"
|
|
||||||
|
|
||||||
"go.mau.fi/mautrix-signal/pkg/signalid"
|
"go.mau.fi/mautrix-signal/pkg/signalid"
|
||||||
"go.mau.fi/mautrix-signal/pkg/signalmeow"
|
"go.mau.fi/mautrix-signal/pkg/signalmeow"
|
||||||
|
|
@ -41,13 +39,11 @@ type SignalClient struct {
|
||||||
Ghost *bridgev2.Ghost
|
Ghost *bridgev2.Ghost
|
||||||
|
|
||||||
queueEmptyWaiter *exsync.Event
|
queueEmptyWaiter *exsync.Event
|
||||||
cancelChatSync atomic.Pointer[context.CancelFunc]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
_ bridgev2.NetworkAPI = (*SignalClient)(nil)
|
_ bridgev2.NetworkAPI = (*SignalClient)(nil)
|
||||||
_ bridgev2.BackgroundSyncingNetworkAPI = (*SignalClient)(nil)
|
_ bridgev2.BackgroundSyncingNetworkAPI = (*SignalClient)(nil)
|
||||||
_ bridgev2.StickerImportingNetworkAPI = (*SignalClient)(nil)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var pushCfg = &bridgev2.PushConfig{
|
var pushCfg = &bridgev2.PushConfig{
|
||||||
|
|
@ -78,19 +74,10 @@ func (s *SignalClient) RegisterPushNotifications(ctx context.Context, pushType b
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SignalClient) DownloadImagePack(ctx context.Context, url string) (*bridgev2.ImportedImagePack, error) {
|
|
||||||
return s.Main.MsgConv.DownloadImagePack(ctx, url)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *SignalClient) ListImagePacks(ctx context.Context) ([]*event.ImagePackMetadata, error) {
|
|
||||||
return []*event.ImagePackMetadata{}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *SignalClient) LogoutRemote(ctx context.Context) {
|
func (s *SignalClient) LogoutRemote(ctx context.Context) {
|
||||||
if s.Client == nil {
|
if s.Client == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
s.stopChatSync()
|
|
||||||
err := s.Client.Unlink(ctx)
|
err := s.Client.Unlink(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
zerolog.Ctx(ctx).Err(err).Msg("Failed to unlink device")
|
zerolog.Ctx(ctx).Err(err).Msg("Failed to unlink device")
|
||||||
|
|
@ -189,7 +176,6 @@ func (s *SignalClient) bridgeStateLoop(statusChan <-chan signalmeow.SignalConnec
|
||||||
}
|
}
|
||||||
|
|
||||||
case signalmeow.SignalConnectionEventLoggedOut:
|
case signalmeow.SignalConnectionEventLoggedOut:
|
||||||
s.stopChatSync()
|
|
||||||
s.UserLogin.Log.Debug().Msg("Sending BadCredentials BridgeState")
|
s.UserLogin.Log.Debug().Msg("Sending BadCredentials BridgeState")
|
||||||
if err == nil {
|
if err == nil {
|
||||||
s.UserLogin.BridgeState.Send(status.BridgeState{StateEvent: status.StateBadCredentials, Message: "You have been logged out of Signal, please reconnect"})
|
s.UserLogin.BridgeState.Send(status.BridgeState{StateEvent: status.StateBadCredentials, Message: "You have been logged out of Signal, please reconnect"})
|
||||||
|
|
@ -288,7 +274,6 @@ func (s *SignalClient) Disconnect() {
|
||||||
if s.Client == nil {
|
if s.Client == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
s.stopChatSync()
|
|
||||||
err := s.Client.StopReceiveLoops()
|
err := s.Client.StopReceiveLoops()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.UserLogin.Log.Err(err).Msg("Failed to stop receive loops")
|
s.UserLogin.Log.Err(err).Msg("Failed to stop receive loops")
|
||||||
|
|
@ -296,18 +281,25 @@ func (s *SignalClient) Disconnect() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SignalClient) postLoginConnect() {
|
func (s *SignalClient) postLoginConnect() {
|
||||||
ctx := s.UserLogin.Log.WithContext(s.Main.Bridge.BackgroundCtx)
|
ctx := s.UserLogin.Log.WithContext(context.Background())
|
||||||
|
// TODO it would be more proper to only connect after syncing,
|
||||||
|
// but currently syncing will fetch group info online, so it has to be connected.
|
||||||
s.tryConnect(ctx, 0, false)
|
s.tryConnect(ctx, 0, false)
|
||||||
|
if s.Client.Store.EphemeralBackupKey != nil {
|
||||||
|
go func() {
|
||||||
|
if s.Client.Store.MasterKey != nil {
|
||||||
|
s.Client.SyncStorage(ctx)
|
||||||
|
} else {
|
||||||
|
s.UserLogin.Log.Warn().Msg("No master key for storage sync before backup sync")
|
||||||
|
}
|
||||||
|
s.syncChats(ctx)
|
||||||
|
}()
|
||||||
|
} else if s.Client.Store.MasterKey != nil {
|
||||||
|
go s.Client.SyncStorage(ctx)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SignalClient) tryConnect(ctx context.Context, retryCount int, noLoginSync bool) {
|
func (s *SignalClient) tryConnect(ctx context.Context, retryCount int, doSync bool) {
|
||||||
if ctx.Err() != nil {
|
|
||||||
zerolog.Ctx(ctx).Debug().
|
|
||||||
Int("retry_count", retryCount).
|
|
||||||
AnErr("ctx_err", ctx.Err()).
|
|
||||||
Msg("Context is canceled, not trying to connect")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if retryCount == 0 {
|
if retryCount == 0 {
|
||||||
s.UserLogin.BridgeState.Send(status.BridgeState{StateEvent: status.StateConnecting})
|
s.UserLogin.BridgeState.Send(status.BridgeState{StateEvent: status.StateConnecting})
|
||||||
}
|
}
|
||||||
|
|
@ -326,33 +318,11 @@ func (s *SignalClient) tryConnect(ctx context.Context, retryCount int, noLoginSy
|
||||||
zerolog.Ctx(ctx).Info().Msg("Context canceled, exit tryConnect")
|
zerolog.Ctx(ctx).Info().Msg("Context canceled, exit tryConnect")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
s.tryConnect(ctx, retryCount+1, noLoginSync)
|
s.tryConnect(ctx, retryCount+1, doSync)
|
||||||
return
|
} else {
|
||||||
}
|
|
||||||
syncCtx, cancel := context.WithCancel(ctx)
|
|
||||||
if oldCancel := s.cancelChatSync.Swap(&cancel); oldCancel != nil {
|
|
||||||
(*oldCancel)()
|
|
||||||
}
|
|
||||||
go s.bridgeStateLoop(ch)
|
go s.bridgeStateLoop(ch)
|
||||||
if noLoginSync {
|
if doSync {
|
||||||
go s.syncChats(syncCtx, cancel)
|
go s.syncChats(ctx)
|
||||||
} else {
|
|
||||||
// TODO it would be more proper to only connect after syncing,
|
|
||||||
// but currently syncing will fetch group info online, so it has to be connected.
|
|
||||||
if s.Client.Store.EphemeralBackupKey != nil {
|
|
||||||
go func() {
|
|
||||||
if s.Client.Store.MasterKey != nil {
|
|
||||||
s.Client.SyncStorage(ctx)
|
|
||||||
} else {
|
|
||||||
s.UserLogin.Log.Warn().Msg("No master key for storage sync before backup sync")
|
|
||||||
}
|
|
||||||
s.syncChats(syncCtx, cancel)
|
|
||||||
}()
|
|
||||||
} else {
|
|
||||||
cancel()
|
|
||||||
if s.Client.Store.MasterKey != nil {
|
|
||||||
go s.Client.SyncStorage(ctx)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"maunium.net/go/mautrix/bridgev2"
|
"maunium.net/go/mautrix/bridgev2"
|
||||||
|
|
@ -29,7 +30,6 @@ func (s *SignalConnector) Download(ctx context.Context, mediaID networkid.MediaI
|
||||||
return nil, fmt.Errorf("failed to parse direct media id: %w", err)
|
return nil, fmt.Errorf("failed to parse direct media id: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var rawDataResp []byte
|
|
||||||
switch info := info.(type) {
|
switch info := info.(type) {
|
||||||
case *signalid.DirectMediaAttachment:
|
case *signalid.DirectMediaAttachment:
|
||||||
log.Info().
|
log.Info().
|
||||||
|
|
@ -76,11 +76,18 @@ func (s *SignalConnector) Download(ctx context.Context, mediaID networkid.MediaI
|
||||||
return nil, fmt.Errorf("failed to to get group master key: %w", err)
|
return nil, fmt.Errorf("failed to to get group master key: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
rawDataResp, err = client.Client.DownloadGroupAvatar(ctx, info.GroupAvatarPath, groupMasterKey)
|
return &mediaproxy.GetMediaResponseCallback{
|
||||||
|
Callback: func(w io.Writer) (int64, error) {
|
||||||
|
data, err := client.Client.DownloadGroupAvatar(ctx, info.GroupAvatarPath, groupMasterKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Err(err).Msg("Direct download failed")
|
log.Err(err).Msg("Direct download failed")
|
||||||
return nil, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_, err = w.Write(data)
|
||||||
|
return int64(len(data)), err
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
case *signalid.DirectMediaProfileAvatar:
|
case *signalid.DirectMediaProfileAvatar:
|
||||||
log.Info().
|
log.Info().
|
||||||
Stringer("user_id", info.UserID).
|
Stringer("user_id", info.UserID).
|
||||||
|
|
@ -104,27 +111,19 @@ func (s *SignalConnector) Download(ctx context.Context, mediaID networkid.MediaI
|
||||||
return nil, fmt.Errorf("profile key not found")
|
return nil, fmt.Errorf("profile key not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
rawDataResp, err = client.Client.DownloadUserAvatar(ctx, info.ProfileAvatarPath, *profileKey)
|
return &mediaproxy.GetMediaResponseCallback{
|
||||||
|
Callback: func(w io.Writer) (int64, error) {
|
||||||
|
data, err := client.Client.DownloadUserAvatar(ctx, info.ProfileAvatarPath, *profileKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Err(err).Msg("Direct download failed")
|
log.Err(err).Msg("Direct download failed")
|
||||||
return nil, err
|
return 0, err
|
||||||
}
|
}
|
||||||
case *signalid.DirectMediaSticker:
|
|
||||||
log.Info().
|
|
||||||
Hex("pack_id", info.PackID).
|
|
||||||
Uint32("sticker_id", info.StickerID).
|
|
||||||
Msg("Direct downloading sticker")
|
|
||||||
|
|
||||||
rawDataResp, err = signalmeow.DownloadStickerPackItem(ctx, info.PackID, info.PackKey, info.StickerID)
|
_, err = w.Write(data)
|
||||||
if err != nil {
|
return int64(len(data)), err
|
||||||
log.Err(err).Msg("Direct download failed")
|
},
|
||||||
return nil, err
|
}, nil
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("no downloader for direct media type: %T", info)
|
return nil, fmt.Errorf("no downloader for direct media type: %T", info)
|
||||||
}
|
}
|
||||||
if rawDataResp == nil {
|
|
||||||
return nil, fmt.Errorf("unexpected fallthrough with no data")
|
|
||||||
}
|
|
||||||
return mediaproxy.GetMediaResponseRawData(rawDataResp), nil
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -137,7 +137,7 @@ func (s *SignalClient) doSendMessage(
|
||||||
}
|
}
|
||||||
msgID := signalid.MakeMessageID(s.Client.Store.ACI, ts)
|
msgID := signalid.MakeMessageID(s.Client.Store.ACI, ts)
|
||||||
msg.AddPendingToIgnore(networkid.TransactionID(msgID))
|
msg.AddPendingToIgnore(networkid.TransactionID(msgID))
|
||||||
err := s.sendMessage(ctx, msg.Portal.ID, signalmeow.WrapDataMessage(converted))
|
err := s.sendMessage(ctx, msg.Portal.ID, &signalpb.Content{DataMessage: converted})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, bridgev2.WrapErrorInStatus(err).WithSendNotice(true)
|
return nil, bridgev2.WrapErrorInStatus(err).WithSendNotice(true)
|
||||||
}
|
}
|
||||||
|
|
@ -173,10 +173,10 @@ func (s *SignalClient) HandleMatrixEdit(ctx context.Context, msg *bridgev2.Matri
|
||||||
}
|
}
|
||||||
ts := getTimestampForEvent(msg.InputTransactionID, msg.Event, msg.OrigSender)
|
ts := getTimestampForEvent(msg.InputTransactionID, msg.Event, msg.OrigSender)
|
||||||
converted.Timestamp = &ts
|
converted.Timestamp = &ts
|
||||||
err = s.sendMessage(ctx, msg.Portal.ID, signalmeow.WrapEditMessage(&signalpb.EditMessage{
|
err = s.sendMessage(ctx, msg.Portal.ID, &signalpb.Content{EditMessage: &signalpb.EditMessage{
|
||||||
TargetSentTimestamp: proto.Uint64(targetSentTimestamp),
|
TargetSentTimestamp: proto.Uint64(targetSentTimestamp),
|
||||||
DataMessage: converted,
|
DataMessage: converted,
|
||||||
}))
|
}})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return bridgev2.WrapErrorInStatus(err).WithSendNotice(true)
|
return bridgev2.WrapErrorInStatus(err).WithSendNotice(true)
|
||||||
}
|
}
|
||||||
|
|
@ -200,7 +200,8 @@ func (s *SignalClient) HandleMatrixReaction(ctx context.Context, msg *bridgev2.M
|
||||||
return nil, fmt.Errorf("failed to parse target message ID: %w", err)
|
return nil, fmt.Errorf("failed to parse target message ID: %w", err)
|
||||||
}
|
}
|
||||||
ts := getTimestampForEvent(msg.InputTransactionID, msg.Event, msg.OrigSender)
|
ts := getTimestampForEvent(msg.InputTransactionID, msg.Event, msg.OrigSender)
|
||||||
err = s.sendMessage(ctx, msg.Portal.ID, signalmeow.WrapDataMessage(&signalpb.DataMessage{
|
wrappedContent := &signalpb.Content{
|
||||||
|
DataMessage: &signalpb.DataMessage{
|
||||||
Timestamp: proto.Uint64(ts),
|
Timestamp: proto.Uint64(ts),
|
||||||
RequiredProtocolVersion: proto.Uint32(uint32(signalpb.DataMessage_REACTIONS)),
|
RequiredProtocolVersion: proto.Uint32(uint32(signalpb.DataMessage_REACTIONS)),
|
||||||
Reaction: &signalpb.DataMessage_Reaction{
|
Reaction: &signalpb.DataMessage_Reaction{
|
||||||
|
|
@ -209,7 +210,9 @@ func (s *SignalClient) HandleMatrixReaction(ctx context.Context, msg *bridgev2.M
|
||||||
TargetAuthorAciBinary: targetAuthorACI[:],
|
TargetAuthorAciBinary: targetAuthorACI[:],
|
||||||
TargetSentTimestamp: proto.Uint64(targetSentTimestamp),
|
TargetSentTimestamp: proto.Uint64(targetSentTimestamp),
|
||||||
},
|
},
|
||||||
}))
|
},
|
||||||
|
}
|
||||||
|
err = s.sendMessage(ctx, msg.Portal.ID, wrappedContent)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -222,7 +225,8 @@ func (s *SignalClient) HandleMatrixReactionRemove(ctx context.Context, msg *brid
|
||||||
return fmt.Errorf("failed to parse target message ID: %w", err)
|
return fmt.Errorf("failed to parse target message ID: %w", err)
|
||||||
}
|
}
|
||||||
ts := getTimestampForEvent(msg.InputTransactionID, msg.Event, msg.OrigSender)
|
ts := getTimestampForEvent(msg.InputTransactionID, msg.Event, msg.OrigSender)
|
||||||
err = s.sendMessage(ctx, msg.Portal.ID, signalmeow.WrapDataMessage(&signalpb.DataMessage{
|
wrappedContent := &signalpb.Content{
|
||||||
|
DataMessage: &signalpb.DataMessage{
|
||||||
Timestamp: proto.Uint64(ts),
|
Timestamp: proto.Uint64(ts),
|
||||||
RequiredProtocolVersion: proto.Uint32(uint32(signalpb.DataMessage_REACTIONS)),
|
RequiredProtocolVersion: proto.Uint32(uint32(signalpb.DataMessage_REACTIONS)),
|
||||||
Reaction: &signalpb.DataMessage_Reaction{
|
Reaction: &signalpb.DataMessage_Reaction{
|
||||||
|
|
@ -231,7 +235,9 @@ func (s *SignalClient) HandleMatrixReactionRemove(ctx context.Context, msg *brid
|
||||||
TargetAuthorAciBinary: targetAuthorACI[:],
|
TargetAuthorAciBinary: targetAuthorACI[:],
|
||||||
TargetSentTimestamp: proto.Uint64(targetSentTimestamp),
|
TargetSentTimestamp: proto.Uint64(targetSentTimestamp),
|
||||||
},
|
},
|
||||||
}))
|
},
|
||||||
|
}
|
||||||
|
err = s.sendMessage(ctx, msg.Portal.ID, wrappedContent)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -246,12 +252,15 @@ func (s *SignalClient) HandleMatrixMessageRemove(ctx context.Context, msg *bridg
|
||||||
return fmt.Errorf("cannot delete other people's messages")
|
return fmt.Errorf("cannot delete other people's messages")
|
||||||
}
|
}
|
||||||
ts := getTimestampForEvent(msg.InputTransactionID, msg.Event, msg.OrigSender)
|
ts := getTimestampForEvent(msg.InputTransactionID, msg.Event, msg.OrigSender)
|
||||||
err = s.sendMessage(ctx, msg.Portal.ID, signalmeow.WrapDataMessage(&signalpb.DataMessage{
|
wrappedContent := &signalpb.Content{
|
||||||
|
DataMessage: &signalpb.DataMessage{
|
||||||
Timestamp: proto.Uint64(ts),
|
Timestamp: proto.Uint64(ts),
|
||||||
Delete: &signalpb.DataMessage_Delete{
|
Delete: &signalpb.DataMessage_Delete{
|
||||||
TargetSentTimestamp: proto.Uint64(targetSentTimestamp),
|
TargetSentTimestamp: proto.Uint64(targetSentTimestamp),
|
||||||
},
|
},
|
||||||
}))
|
},
|
||||||
|
}
|
||||||
|
err = s.sendMessage(ctx, msg.Portal.ID, wrappedContent)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -378,7 +387,7 @@ func (s *SignalClient) HandleMatrixRoomAvatar(ctx context.Context, msg *bridgev2
|
||||||
return false, fmt.Errorf("failed to download avatar: %w", err)
|
return false, fmt.Errorf("failed to download avatar: %w", err)
|
||||||
}
|
}
|
||||||
avatarHash = sha256.Sum256(data)
|
avatarHash = sha256.Sum256(data)
|
||||||
avatarPath, err = s.Client.UploadGroupAvatar(ctx, data, groupID, "")
|
avatarPath, err = s.Client.UploadGroupAvatar(ctx, data, groupID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, fmt.Errorf("failed to reupload avatar: %w", err)
|
return false, fmt.Errorf("failed to reupload avatar: %w", err)
|
||||||
}
|
}
|
||||||
|
|
@ -398,9 +407,6 @@ func (s *SignalClient) HandleMatrixRoomTopic(ctx context.Context, msg *bridgev2.
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SignalClient) HandleMatrixMembership(ctx context.Context, msg *bridgev2.MatrixMembershipChange) (*bridgev2.MatrixMembershipResult, error) {
|
func (s *SignalClient) HandleMatrixMembership(ctx context.Context, msg *bridgev2.MatrixMembershipChange) (*bridgev2.MatrixMembershipResult, error) {
|
||||||
if msg.Type.IsSelf && msg.OrigSender != nil {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
var targetIntent bridgev2.MatrixAPI
|
var targetIntent bridgev2.MatrixAPI
|
||||||
var targetSignalID libsignalgo.ServiceID
|
var targetSignalID libsignalgo.ServiceID
|
||||||
var err error
|
var err error
|
||||||
|
|
@ -679,11 +685,13 @@ func (s *SignalClient) HandleMatrixDisappearingTimer(ctx context.Context, msg *b
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
ts := getTimestampForEvent(msg.InputTransactionID, msg.Event, msg.OrigSender)
|
ts := getTimestampForEvent(msg.InputTransactionID, msg.Event, msg.OrigSender)
|
||||||
res := s.Client.SendMessage(ctx, userID, signalmeow.WrapDataMessage(&signalpb.DataMessage{
|
res := s.Client.SendMessage(ctx, userID, &signalpb.Content{
|
||||||
|
DataMessage: &signalpb.DataMessage{
|
||||||
Timestamp: ptr.Ptr(ts),
|
Timestamp: ptr.Ptr(ts),
|
||||||
Flags: ptr.Ptr(uint32(signalpb.DataMessage_EXPIRATION_TIMER_UPDATE)),
|
Flags: ptr.Ptr(uint32(signalpb.DataMessage_EXPIRATION_TIMER_UPDATE)),
|
||||||
ExpireTimer: ptr.Ptr(uint32(msg.Content.Timer.Seconds())),
|
ExpireTimer: ptr.Ptr(uint32(msg.Content.Timer.Seconds())),
|
||||||
}))
|
},
|
||||||
|
})
|
||||||
if !res.WasSuccessful {
|
if !res.WasSuccessful {
|
||||||
return false, res.Error
|
return false, res.Error
|
||||||
}
|
}
|
||||||
|
|
@ -762,8 +770,8 @@ func (s *SignalClient) HandleMatrixDeleteChat(ctx context.Context, msg *bridgev2
|
||||||
|
|
||||||
recipientID := s.Client.Store.ACIServiceID()
|
recipientID := s.Client.Store.ACIServiceID()
|
||||||
// Send DeleteForMe sync message to self
|
// Send DeleteForMe sync message to self
|
||||||
result := s.Client.SendMessage(ctx, recipientID, signalmeow.WrapSyncMessage(&signalpb.SyncMessage{
|
result := s.Client.SendMessage(ctx, recipientID, &signalpb.Content{
|
||||||
Content: &signalpb.SyncMessage_DeleteForMe_{
|
SyncMessage: &signalpb.SyncMessage{
|
||||||
DeleteForMe: &signalpb.SyncMessage_DeleteForMe{
|
DeleteForMe: &signalpb.SyncMessage_DeleteForMe{
|
||||||
ConversationDeletes: []*signalpb.SyncMessage_DeleteForMe_ConversationDelete{{
|
ConversationDeletes: []*signalpb.SyncMessage_DeleteForMe_ConversationDelete{{
|
||||||
Conversation: conversationID,
|
Conversation: conversationID,
|
||||||
|
|
@ -772,7 +780,7 @@ func (s *SignalClient) HandleMatrixDeleteChat(ctx context.Context, msg *bridgev2
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}))
|
})
|
||||||
|
|
||||||
zerolog.Ctx(ctx).Debug().
|
zerolog.Ctx(ctx).Debug().
|
||||||
Str("portal_id", string(msg.Portal.ID)).
|
Str("portal_id", string(msg.Portal.ID)).
|
||||||
|
|
@ -857,11 +865,11 @@ func (s *SignalClient) syncMessageRequestResponse(
|
||||||
} else {
|
} else {
|
||||||
return fmt.Errorf("invalid portal ID for message request response: %s", portal.ID)
|
return fmt.Errorf("invalid portal ID for message request response: %s", portal.ID)
|
||||||
}
|
}
|
||||||
res := s.Client.SendMessage(ctx, libsignalgo.NewACIServiceID(s.Client.Store.ACI), signalmeow.WrapSyncMessage(&signalpb.SyncMessage{
|
res := s.Client.SendMessage(ctx, libsignalgo.NewACIServiceID(s.Client.Store.ACI), &signalpb.Content{
|
||||||
Content: &signalpb.SyncMessage_MessageRequestResponse_{
|
SyncMessage: &signalpb.SyncMessage{
|
||||||
MessageRequestResponse: accept,
|
MessageRequestResponse: accept,
|
||||||
},
|
},
|
||||||
}))
|
})
|
||||||
if !res.WasSuccessful {
|
if !res.WasSuccessful {
|
||||||
return res.Error
|
return res.Error
|
||||||
}
|
}
|
||||||
|
|
@ -894,13 +902,13 @@ func (s *SignalClient) HandleMatrixAcceptMessageRequest(ctx context.Context, msg
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
res := s.Client.SendMessage(ctx, userID, &signalpb.Content{
|
res := s.Client.SendMessage(ctx, userID, &signalpb.Content{
|
||||||
Content: &signalpb.Content_DataMessage{DataMessage: &signalpb.DataMessage{
|
DataMessage: &signalpb.DataMessage{
|
||||||
Flags: proto.Uint32(uint32(signalpb.DataMessage_PROFILE_KEY_UPDATE)),
|
Flags: proto.Uint32(uint32(signalpb.DataMessage_PROFILE_KEY_UPDATE)),
|
||||||
ProfileKey: profileKey.Slice(),
|
ProfileKey: profileKey.Slice(),
|
||||||
Timestamp: proto.Uint64(getTimestampForEvent(msg.InputTransactionID, msg.Event, msg.OrigSender)),
|
Timestamp: proto.Uint64(getTimestampForEvent(msg.InputTransactionID, msg.Event, msg.OrigSender)),
|
||||||
|
|
||||||
RequiredProtocolVersion: proto.Uint32(0),
|
RequiredProtocolVersion: proto.Uint32(0),
|
||||||
}},
|
},
|
||||||
PniSignatureMessage: pniSig,
|
PniSignatureMessage: pniSig,
|
||||||
})
|
})
|
||||||
if !res.WasSuccessful {
|
if !res.WasSuccessful {
|
||||||
|
|
|
||||||
|
|
@ -184,7 +184,7 @@ func (evt *Bv2ChatEvent) GetType() bridgev2.RemoteEventType {
|
||||||
return bridgev2.RemoteEventReactionRemove
|
return bridgev2.RemoteEventReactionRemove
|
||||||
}
|
}
|
||||||
return bridgev2.RemoteEventReaction
|
return bridgev2.RemoteEventReaction
|
||||||
case innerEvt.Delete != nil, innerEvt.AdminDelete != nil:
|
case innerEvt.Delete != nil:
|
||||||
return bridgev2.RemoteEventMessageRemove
|
return bridgev2.RemoteEventMessageRemove
|
||||||
case innerEvt.GetGroupV2().GetGroupChange() != nil:
|
case innerEvt.GetGroupV2().GetGroupChange() != nil:
|
||||||
return bridgev2.RemoteEventChatInfoChange
|
return bridgev2.RemoteEventChatInfoChange
|
||||||
|
|
@ -303,11 +303,6 @@ func (evt *Bv2ChatEvent) GetTargetMessage() networkid.MessageID {
|
||||||
targetSentTS = innerEvt.Reaction.GetTargetSentTimestamp()
|
targetSentTS = innerEvt.Reaction.GetTargetSentTimestamp()
|
||||||
case innerEvt.Delete != nil:
|
case innerEvt.Delete != nil:
|
||||||
targetSentTS = innerEvt.Delete.GetTargetSentTimestamp()
|
targetSentTS = innerEvt.Delete.GetTargetSentTimestamp()
|
||||||
case innerEvt.AdminDelete != nil:
|
|
||||||
if len(innerEvt.AdminDelete.GetTargetAuthorAciBinary()) == 16 {
|
|
||||||
targetAuthorACI = uuid.UUID(innerEvt.AdminDelete.GetTargetAuthorAciBinary())
|
|
||||||
}
|
|
||||||
targetSentTS = innerEvt.AdminDelete.GetTargetSentTimestamp()
|
|
||||||
default:
|
default:
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
@ -426,7 +421,7 @@ func (b *Bv2Receipt) GetReadUpTo() time.Time {
|
||||||
return time.Time{}
|
return time.Time{}
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ bridgev2.RemoteReadReceipt = (*Bv2Receipt)(nil)
|
var _ bridgev2.RemoteReceipt = (*Bv2Receipt)(nil)
|
||||||
|
|
||||||
func convertReceipts[T any](ctx context.Context, input []T, getMessageFunc func(ctx context.Context, msgID T) (*database.Message, error)) map[networkid.PortalKey]*Bv2Receipt {
|
func convertReceipts[T any](ctx context.Context, input []T, getMessageFunc func(ctx context.Context, msgID T) (*database.Message, error)) map[networkid.PortalKey]*Bv2Receipt {
|
||||||
log := zerolog.Ctx(ctx)
|
log := zerolog.Ctx(ctx)
|
||||||
|
|
@ -472,7 +467,7 @@ func (s *SignalClient) handleSignalReceipt(evt *events.Receipt) bool {
|
||||||
Stringer("sender_id", evt.Sender).
|
Stringer("sender_id", evt.Sender).
|
||||||
Stringer("receipt_type", evt.Content.GetType()).
|
Stringer("receipt_type", evt.Content.GetType()).
|
||||||
Logger()
|
Logger()
|
||||||
ctx := log.WithContext(s.Main.Bridge.BackgroundCtx)
|
ctx := log.WithContext(context.TODO())
|
||||||
receipts := convertReceipts(ctx, evt.Content.Timestamp, func(ctx context.Context, msgTS uint64) (*database.Message, error) {
|
receipts := convertReceipts(ctx, evt.Content.Timestamp, func(ctx context.Context, msgTS uint64) (*database.Message, error) {
|
||||||
return s.Main.Bridge.DB.Message.GetFirstPartByID(ctx, s.UserLogin.ID, signalid.MakeMessageID(s.Client.Store.ACI, msgTS))
|
return s.Main.Bridge.DB.Message.GetFirstPartByID(ctx, s.UserLogin.ID, signalid.MakeMessageID(s.Client.Store.ACI, msgTS))
|
||||||
})
|
})
|
||||||
|
|
@ -483,7 +478,7 @@ func (s *SignalClient) handleSignalReadSelf(evt *events.ReadSelf) bool {
|
||||||
log := s.UserLogin.Log.With().
|
log := s.UserLogin.Log.With().
|
||||||
Str("action", "handle signal read self").
|
Str("action", "handle signal read self").
|
||||||
Logger()
|
Logger()
|
||||||
ctx := log.WithContext(s.Main.Bridge.BackgroundCtx)
|
ctx := log.WithContext(context.TODO())
|
||||||
receipts := convertReceipts(ctx, evt.Messages, func(ctx context.Context, msgInfo *signalpb.SyncMessage_Read) (*database.Message, error) {
|
receipts := convertReceipts(ctx, evt.Messages, func(ctx context.Context, msgInfo *signalpb.SyncMessage_Read) (*database.Message, error) {
|
||||||
aciUUID, err := signalmeow.ParseStringOrBinaryUUID(msgInfo.GetSenderAci(), msgInfo.GetSenderAciBinary())
|
aciUUID, err := signalmeow.ParseStringOrBinaryUUID(msgInfo.GetSenderAci(), msgInfo.GetSenderAciBinary())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -693,7 +688,7 @@ func (s *SignalClient) handleSignalACIFound(evt *events.ACIFound) {
|
||||||
Stringer("aci", evt.ACI).
|
Stringer("aci", evt.ACI).
|
||||||
Stringer("pni", evt.PNI).
|
Stringer("pni", evt.PNI).
|
||||||
Logger()
|
Logger()
|
||||||
ctx := log.WithContext(s.Main.Bridge.BackgroundCtx)
|
ctx := log.WithContext(context.TODO())
|
||||||
pniPortalKey := s.makeDMPortalKey(evt.PNI)
|
pniPortalKey := s.makeDMPortalKey(evt.PNI)
|
||||||
aciPortalKey := s.makeDMPortalKey(evt.ACI)
|
aciPortalKey := s.makeDMPortalKey(evt.ACI)
|
||||||
result, portal, err := s.Main.Bridge.ReIDPortal(ctx, pniPortalKey, aciPortalKey)
|
result, portal, err := s.Main.Bridge.ReIDPortal(ctx, pniPortalKey, aciPortalKey)
|
||||||
|
|
@ -713,7 +708,7 @@ func (s *SignalClient) handleSignalACIFound(evt *events.ACIFound) {
|
||||||
|
|
||||||
func (s *SignalClient) handleSignalContactList(evt *events.ContactList) {
|
func (s *SignalClient) handleSignalContactList(evt *events.ContactList) {
|
||||||
log := s.UserLogin.Log.With().Str("action", "handle contact list").Logger()
|
log := s.UserLogin.Log.With().Str("action", "handle contact list").Logger()
|
||||||
ctx := log.WithContext(s.Main.Bridge.BackgroundCtx)
|
ctx := log.WithContext(context.TODO())
|
||||||
for _, contact := range evt.Contacts {
|
for _, contact := range evt.Contacts {
|
||||||
if contact.ACI == uuid.Nil {
|
if contact.ACI == uuid.Nil {
|
||||||
continue
|
continue
|
||||||
|
|
|
||||||
|
|
@ -159,11 +159,11 @@ func signal_destroy_identity_key_store_callback(storeCtx unsafe.Pointer) {
|
||||||
func (ctx *CallbackContext) wrapIdentityKeyStore(store IdentityKeyStore) C.SignalConstPointerFfiIdentityKeyStoreStruct {
|
func (ctx *CallbackContext) wrapIdentityKeyStore(store IdentityKeyStore) C.SignalConstPointerFfiIdentityKeyStoreStruct {
|
||||||
return C.SignalConstPointerFfiIdentityKeyStoreStruct{&C.SignalIdentityKeyStore{
|
return C.SignalConstPointerFfiIdentityKeyStoreStruct{&C.SignalIdentityKeyStore{
|
||||||
ctx: wrapStore(ctx, store),
|
ctx: wrapStore(ctx, store),
|
||||||
get_local_identity_key_pair: C.SignalFfiIdentityKeyStoreGetLocalIdentityKeyPair(C.signal_get_identity_key_pair_callback),
|
get_local_identity_key_pair: C.SignalFfiBridgeIdentityKeyStoreGetLocalIdentityKeyPair(C.signal_get_identity_key_pair_callback),
|
||||||
get_local_registration_id: C.SignalFfiIdentityKeyStoreGetLocalRegistrationId(C.signal_get_local_registration_id_callback),
|
get_local_registration_id: C.SignalFfiBridgeIdentityKeyStoreGetLocalRegistrationId(C.signal_get_local_registration_id_callback),
|
||||||
get_identity_key: C.SignalFfiIdentityKeyStoreGetIdentityKey(C.signal_get_identity_key_callback),
|
get_identity_key: C.SignalFfiBridgeIdentityKeyStoreGetIdentityKey(C.signal_get_identity_key_callback),
|
||||||
save_identity_key: C.SignalFfiIdentityKeyStoreSaveIdentityKey(C.signal_save_identity_key_callback),
|
save_identity_key: C.SignalFfiBridgeIdentityKeyStoreSaveIdentityKey(C.signal_save_identity_key_callback),
|
||||||
is_trusted_identity: C.SignalFfiIdentityKeyStoreIsTrustedIdentity(C.signal_is_trusted_identity_callback),
|
is_trusted_identity: C.SignalFfiBridgeIdentityKeyStoreIsTrustedIdentity(C.signal_is_trusted_identity_callback),
|
||||||
destroy: C.SignalFfiIdentityKeyStoreDestroy(C.signal_destroy_identity_key_store_callback),
|
destroy: C.SignalFfiBridgeIdentityKeyStoreDestroy(C.signal_destroy_identity_key_store_callback),
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -77,9 +77,9 @@ func signal_destroy_kyber_pre_key_store_callback(storeCtx unsafe.Pointer) {
|
||||||
func (ctx *CallbackContext) wrapKyberPreKeyStore(store KyberPreKeyStore) C.SignalConstPointerFfiKyberPreKeyStoreStruct {
|
func (ctx *CallbackContext) wrapKyberPreKeyStore(store KyberPreKeyStore) C.SignalConstPointerFfiKyberPreKeyStoreStruct {
|
||||||
return C.SignalConstPointerFfiKyberPreKeyStoreStruct{&C.SignalKyberPreKeyStore{
|
return C.SignalConstPointerFfiKyberPreKeyStoreStruct{&C.SignalKyberPreKeyStore{
|
||||||
ctx: wrapStore(ctx, store),
|
ctx: wrapStore(ctx, store),
|
||||||
load_kyber_pre_key: C.SignalFfiKyberPreKeyStoreLoadKyberPreKey(C.signal_load_kyber_pre_key_callback),
|
load_kyber_pre_key: C.SignalFfiBridgeKyberPreKeyStoreLoadKyberPreKey(C.signal_load_kyber_pre_key_callback),
|
||||||
store_kyber_pre_key: C.SignalFfiKyberPreKeyStoreStoreKyberPreKey(C.signal_store_kyber_pre_key_callback),
|
store_kyber_pre_key: C.SignalFfiBridgeKyberPreKeyStoreStoreKyberPreKey(C.signal_store_kyber_pre_key_callback),
|
||||||
mark_kyber_pre_key_used: C.SignalFfiKyberPreKeyStoreMarkKyberPreKeyUsed(C.signal_mark_kyber_pre_key_used_callback),
|
mark_kyber_pre_key_used: C.SignalFfiBridgeKyberPreKeyStoreMarkKyberPreKeyUsed(C.signal_mark_kyber_pre_key_used_callback),
|
||||||
destroy: C.SignalFfiKyberPreKeyStoreDestroy(C.signal_destroy_kyber_pre_key_store_callback),
|
destroy: C.SignalFfiBridgeKyberPreKeyStoreDestroy(C.signal_destroy_kyber_pre_key_store_callback),
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
Subproject commit bbc16886cae2feab1cd1fe271ccc651e8860ce96
|
Subproject commit a5e76674882a89bac1ed3f4a982120652966d21e
|
||||||
|
|
@ -261,7 +261,6 @@ typedef enum {
|
||||||
SignalErrorCodeRequestUnauthorized = 220,
|
SignalErrorCodeRequestUnauthorized = 220,
|
||||||
SignalErrorCodeMismatchedDevices = 221,
|
SignalErrorCodeMismatchedDevices = 221,
|
||||||
SignalErrorCodeServiceIdNotFound = 222,
|
SignalErrorCodeServiceIdNotFound = 222,
|
||||||
SignalErrorCodeUploadTooLarge = 223,
|
|
||||||
} SignalErrorCode;
|
} SignalErrorCode;
|
||||||
|
|
||||||
enum SignalSvr2CredentialsResult {
|
enum SignalSvr2CredentialsResult {
|
||||||
|
|
@ -512,46 +511,6 @@ typedef struct {
|
||||||
const SignalAuthenticatedChatConnection *raw;
|
const SignalAuthenticatedChatConnection *raw;
|
||||||
} SignalConstPointerAuthenticatedChatConnection;
|
} SignalConstPointerAuthenticatedChatConnection;
|
||||||
|
|
||||||
/**
|
|
||||||
* A type alias to be used with [`OwnedBufferOf`], so that `OwnedBufferOf<c_char>` and
|
|
||||||
* `OwnedBufferOf<*const c_char>` get distinct names.
|
|
||||||
*/
|
|
||||||
typedef const char *SignalCStringPtr;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A representation of a array allocated on the Rust heap for use in C code.
|
|
||||||
*/
|
|
||||||
typedef struct {
|
|
||||||
SignalCStringPtr *base;
|
|
||||||
/**
|
|
||||||
* The number of elements in the buffer (not necessarily the number of bytes).
|
|
||||||
*/
|
|
||||||
size_t length;
|
|
||||||
} SignalOwnedBufferOfCStringPtr;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint32_t cdn;
|
|
||||||
SignalCStringPtr key;
|
|
||||||
SignalOwnedBufferOfCStringPtr header_keys;
|
|
||||||
SignalOwnedBufferOfCStringPtr header_values;
|
|
||||||
SignalCStringPtr signed_upload_url;
|
|
||||||
} SignalFfiUploadForm;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A C callback used to report the results of Rust futures.
|
|
||||||
*
|
|
||||||
* cbindgen will produce independent C types like `SignalCPromisei32` and
|
|
||||||
* `SignalCPromiseProtocolAddress`.
|
|
||||||
*
|
|
||||||
* This derives Copy because it behaves like a C type; nevertheless, a promise should still only be
|
|
||||||
* completed once.
|
|
||||||
*/
|
|
||||||
typedef struct {
|
|
||||||
void (*complete)(SignalFfiError *error, const SignalFfiUploadForm *result, const void *context);
|
|
||||||
const void *context;
|
|
||||||
SignalCancellationId cancellation_id;
|
|
||||||
} SignalCPromiseFfiUploadForm;
|
|
||||||
|
|
||||||
typedef SignalConnectionInfo SignalChatConnectionInfo;
|
typedef SignalConnectionInfo SignalChatConnectionInfo;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
@ -603,6 +562,23 @@ typedef struct {
|
||||||
const SignalFfiChatListenerStruct *raw;
|
const SignalFfiChatListenerStruct *raw;
|
||||||
} SignalConstPointerFfiChatListenerStruct;
|
} SignalConstPointerFfiChatListenerStruct;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A type alias to be used with [`OwnedBufferOf`], so that `OwnedBufferOf<c_char>` and
|
||||||
|
* `OwnedBufferOf<*const c_char>` get distinct names.
|
||||||
|
*/
|
||||||
|
typedef const char *SignalCStringPtr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A representation of a array allocated on the Rust heap for use in C code.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
SignalCStringPtr *base;
|
||||||
|
/**
|
||||||
|
* The number of elements in the buffer (not necessarily the number of bytes).
|
||||||
|
*/
|
||||||
|
size_t length;
|
||||||
|
} SignalOwnedBufferOfCStringPtr;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint16_t status;
|
uint16_t status;
|
||||||
const char *message;
|
const char *message;
|
||||||
|
|
@ -629,27 +605,6 @@ typedef struct {
|
||||||
const SignalHttpRequest *raw;
|
const SignalHttpRequest *raw;
|
||||||
} SignalConstPointerHttpRequest;
|
} SignalConstPointerHttpRequest;
|
||||||
|
|
||||||
/**
|
|
||||||
* The fixed-width binary representation of a ServiceId.
|
|
||||||
*
|
|
||||||
* Rarely used. The variable-width format that privileges ACIs is preferred.
|
|
||||||
*/
|
|
||||||
typedef uint8_t SignalServiceIdFixedWidthBinaryBytes[17];
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
const uint32_t *base;
|
|
||||||
size_t length;
|
|
||||||
} SignalBorrowedSliceOfu32;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
const SignalCiphertextMessage *raw;
|
|
||||||
} SignalConstPointerCiphertextMessage;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
const SignalConstPointerCiphertextMessage *base;
|
|
||||||
size_t length;
|
|
||||||
} SignalBorrowedSliceOfConstPointerCiphertextMessage;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A wrapper type for raw UUIDs, because C treats arrays specially in argument position.
|
* A wrapper type for raw UUIDs, because C treats arrays specially in argument position.
|
||||||
*/
|
*/
|
||||||
|
|
@ -657,6 +612,13 @@ typedef struct {
|
||||||
uint8_t bytes[16];
|
uint8_t bytes[16];
|
||||||
} SignalUuid;
|
} SignalUuid;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The fixed-width binary representation of a ServiceId.
|
||||||
|
*
|
||||||
|
* Rarely used. The variable-width format that privileges ACIs is preferred.
|
||||||
|
*/
|
||||||
|
typedef uint8_t SignalServiceIdFixedWidthBinaryBytes[17];
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
SignalPrivateKey *raw;
|
SignalPrivateKey *raw;
|
||||||
} SignalMutPointerPrivateKey;
|
} SignalMutPointerPrivateKey;
|
||||||
|
|
@ -768,6 +730,10 @@ typedef struct {
|
||||||
const SignalPlaintextContent *raw;
|
const SignalPlaintextContent *raw;
|
||||||
} SignalConstPointerPlaintextContent;
|
} SignalConstPointerPlaintextContent;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const SignalCiphertextMessage *raw;
|
||||||
|
} SignalConstPointerCiphertextMessage;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
SignalConnectionInfo *raw;
|
SignalConnectionInfo *raw;
|
||||||
} SignalMutPointerConnectionInfo;
|
} SignalMutPointerConnectionInfo;
|
||||||
|
|
@ -792,18 +758,20 @@ typedef struct {
|
||||||
SignalSessionRecord *raw;
|
SignalSessionRecord *raw;
|
||||||
} SignalMutPointerSessionRecord;
|
} SignalMutPointerSessionRecord;
|
||||||
|
|
||||||
typedef int (*SignalFfiSessionStoreLoadSession)(void *ctx, SignalMutPointerSessionRecord *out, SignalMutPointerProtocolAddress address);
|
typedef int (*SignalFfiBridgeSessionStoreLoadSession)(void *ctx, SignalMutPointerSessionRecord *out, SignalMutPointerProtocolAddress address);
|
||||||
|
|
||||||
typedef int (*SignalFfiSessionStoreStoreSession)(void *ctx, SignalMutPointerProtocolAddress address, SignalMutPointerSessionRecord record);
|
typedef int (*SignalFfiBridgeSessionStoreStoreSession)(void *ctx, SignalMutPointerProtocolAddress address, SignalMutPointerSessionRecord record);
|
||||||
|
|
||||||
typedef void (*SignalFfiSessionStoreDestroy)(void *ctx);
|
typedef void (*SignalFfiBridgeSessionStoreDestroy)(void *ctx);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
void *ctx;
|
void *ctx;
|
||||||
SignalFfiSessionStoreLoadSession load_session;
|
SignalFfiBridgeSessionStoreLoadSession load_session;
|
||||||
SignalFfiSessionStoreStoreSession store_session;
|
SignalFfiBridgeSessionStoreStoreSession store_session;
|
||||||
SignalFfiSessionStoreDestroy destroy;
|
SignalFfiBridgeSessionStoreDestroy destroy;
|
||||||
} SignalSessionStore;
|
} SignalFfiBridgeSessionStoreStruct;
|
||||||
|
|
||||||
|
typedef SignalFfiBridgeSessionStoreStruct SignalSessionStore;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
const SignalSessionStore *raw;
|
const SignalSessionStore *raw;
|
||||||
|
|
@ -818,27 +786,29 @@ typedef struct {
|
||||||
SignalMutPointerPublicKey second;
|
SignalMutPointerPublicKey second;
|
||||||
} SignalPairOfMutPointerPrivateKeyMutPointerPublicKey;
|
} SignalPairOfMutPointerPrivateKeyMutPointerPublicKey;
|
||||||
|
|
||||||
typedef int (*SignalFfiIdentityKeyStoreGetLocalIdentityKeyPair)(void *ctx, SignalPairOfMutPointerPrivateKeyMutPointerPublicKey *out);
|
typedef int (*SignalFfiBridgeIdentityKeyStoreGetLocalIdentityKeyPair)(void *ctx, SignalPairOfMutPointerPrivateKeyMutPointerPublicKey *out);
|
||||||
|
|
||||||
typedef int (*SignalFfiIdentityKeyStoreGetLocalRegistrationId)(void *ctx, uint32_t *out);
|
typedef int (*SignalFfiBridgeIdentityKeyStoreGetLocalRegistrationId)(void *ctx, uint32_t *out);
|
||||||
|
|
||||||
typedef int (*SignalFfiIdentityKeyStoreGetIdentityKey)(void *ctx, SignalMutPointerPublicKey *out, SignalMutPointerProtocolAddress address);
|
typedef int (*SignalFfiBridgeIdentityKeyStoreGetIdentityKey)(void *ctx, SignalMutPointerPublicKey *out, SignalMutPointerProtocolAddress address);
|
||||||
|
|
||||||
typedef int (*SignalFfiIdentityKeyStoreSaveIdentityKey)(void *ctx, uint8_t *out, SignalMutPointerProtocolAddress address, SignalMutPointerPublicKey public_key);
|
typedef int (*SignalFfiBridgeIdentityKeyStoreSaveIdentityKey)(void *ctx, uint8_t *out, SignalMutPointerProtocolAddress address, SignalMutPointerPublicKey public_key);
|
||||||
|
|
||||||
typedef int (*SignalFfiIdentityKeyStoreIsTrustedIdentity)(void *ctx, bool *out, SignalMutPointerProtocolAddress address, SignalMutPointerPublicKey public_key, uint32_t direction);
|
typedef int (*SignalFfiBridgeIdentityKeyStoreIsTrustedIdentity)(void *ctx, bool *out, SignalMutPointerProtocolAddress address, SignalMutPointerPublicKey public_key, uint32_t direction);
|
||||||
|
|
||||||
typedef void (*SignalFfiIdentityKeyStoreDestroy)(void *ctx);
|
typedef void (*SignalFfiBridgeIdentityKeyStoreDestroy)(void *ctx);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
void *ctx;
|
void *ctx;
|
||||||
SignalFfiIdentityKeyStoreGetLocalIdentityKeyPair get_local_identity_key_pair;
|
SignalFfiBridgeIdentityKeyStoreGetLocalIdentityKeyPair get_local_identity_key_pair;
|
||||||
SignalFfiIdentityKeyStoreGetLocalRegistrationId get_local_registration_id;
|
SignalFfiBridgeIdentityKeyStoreGetLocalRegistrationId get_local_registration_id;
|
||||||
SignalFfiIdentityKeyStoreGetIdentityKey get_identity_key;
|
SignalFfiBridgeIdentityKeyStoreGetIdentityKey get_identity_key;
|
||||||
SignalFfiIdentityKeyStoreSaveIdentityKey save_identity_key;
|
SignalFfiBridgeIdentityKeyStoreSaveIdentityKey save_identity_key;
|
||||||
SignalFfiIdentityKeyStoreIsTrustedIdentity is_trusted_identity;
|
SignalFfiBridgeIdentityKeyStoreIsTrustedIdentity is_trusted_identity;
|
||||||
SignalFfiIdentityKeyStoreDestroy destroy;
|
SignalFfiBridgeIdentityKeyStoreDestroy destroy;
|
||||||
} SignalIdentityKeyStore;
|
} SignalFfiBridgeIdentityKeyStoreStruct;
|
||||||
|
|
||||||
|
typedef SignalFfiBridgeIdentityKeyStoreStruct SignalIdentityKeyStore;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
const SignalIdentityKeyStore *raw;
|
const SignalIdentityKeyStore *raw;
|
||||||
|
|
@ -852,21 +822,23 @@ typedef struct {
|
||||||
SignalPreKeyRecord *raw;
|
SignalPreKeyRecord *raw;
|
||||||
} SignalMutPointerPreKeyRecord;
|
} SignalMutPointerPreKeyRecord;
|
||||||
|
|
||||||
typedef int (*SignalFfiPreKeyStoreLoadPreKey)(void *ctx, SignalMutPointerPreKeyRecord *out, uint32_t id);
|
typedef int (*SignalFfiBridgePreKeyStoreLoadPreKey)(void *ctx, SignalMutPointerPreKeyRecord *out, uint32_t id);
|
||||||
|
|
||||||
typedef int (*SignalFfiPreKeyStoreStorePreKey)(void *ctx, uint32_t id, SignalMutPointerPreKeyRecord record);
|
typedef int (*SignalFfiBridgePreKeyStoreStorePreKey)(void *ctx, uint32_t id, SignalMutPointerPreKeyRecord record);
|
||||||
|
|
||||||
typedef int (*SignalFfiPreKeyStoreRemovePreKey)(void *ctx, uint32_t id);
|
typedef int (*SignalFfiBridgePreKeyStoreRemovePreKey)(void *ctx, uint32_t id);
|
||||||
|
|
||||||
typedef void (*SignalFfiPreKeyStoreDestroy)(void *ctx);
|
typedef void (*SignalFfiBridgePreKeyStoreDestroy)(void *ctx);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
void *ctx;
|
void *ctx;
|
||||||
SignalFfiPreKeyStoreLoadPreKey load_pre_key;
|
SignalFfiBridgePreKeyStoreLoadPreKey load_pre_key;
|
||||||
SignalFfiPreKeyStoreStorePreKey store_pre_key;
|
SignalFfiBridgePreKeyStoreStorePreKey store_pre_key;
|
||||||
SignalFfiPreKeyStoreRemovePreKey remove_pre_key;
|
SignalFfiBridgePreKeyStoreRemovePreKey remove_pre_key;
|
||||||
SignalFfiPreKeyStoreDestroy destroy;
|
SignalFfiBridgePreKeyStoreDestroy destroy;
|
||||||
} SignalPreKeyStore;
|
} SignalFfiBridgePreKeyStoreStruct;
|
||||||
|
|
||||||
|
typedef SignalFfiBridgePreKeyStoreStruct SignalPreKeyStore;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
const SignalPreKeyStore *raw;
|
const SignalPreKeyStore *raw;
|
||||||
|
|
@ -876,18 +848,20 @@ typedef struct {
|
||||||
SignalSignedPreKeyRecord *raw;
|
SignalSignedPreKeyRecord *raw;
|
||||||
} SignalMutPointerSignedPreKeyRecord;
|
} SignalMutPointerSignedPreKeyRecord;
|
||||||
|
|
||||||
typedef int (*SignalFfiSignedPreKeyStoreLoadSignedPreKey)(void *ctx, SignalMutPointerSignedPreKeyRecord *out, uint32_t id);
|
typedef int (*SignalFfiBridgeSignedPreKeyStoreLoadSignedPreKey)(void *ctx, SignalMutPointerSignedPreKeyRecord *out, uint32_t id);
|
||||||
|
|
||||||
typedef int (*SignalFfiSignedPreKeyStoreStoreSignedPreKey)(void *ctx, uint32_t id, SignalMutPointerSignedPreKeyRecord record);
|
typedef int (*SignalFfiBridgeSignedPreKeyStoreStoreSignedPreKey)(void *ctx, uint32_t id, SignalMutPointerSignedPreKeyRecord record);
|
||||||
|
|
||||||
typedef void (*SignalFfiSignedPreKeyStoreDestroy)(void *ctx);
|
typedef void (*SignalFfiBridgeSignedPreKeyStoreDestroy)(void *ctx);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
void *ctx;
|
void *ctx;
|
||||||
SignalFfiSignedPreKeyStoreLoadSignedPreKey load_signed_pre_key;
|
SignalFfiBridgeSignedPreKeyStoreLoadSignedPreKey load_signed_pre_key;
|
||||||
SignalFfiSignedPreKeyStoreStoreSignedPreKey store_signed_pre_key;
|
SignalFfiBridgeSignedPreKeyStoreStoreSignedPreKey store_signed_pre_key;
|
||||||
SignalFfiSignedPreKeyStoreDestroy destroy;
|
SignalFfiBridgeSignedPreKeyStoreDestroy destroy;
|
||||||
} SignalSignedPreKeyStore;
|
} SignalFfiBridgeSignedPreKeyStoreStruct;
|
||||||
|
|
||||||
|
typedef SignalFfiBridgeSignedPreKeyStoreStruct SignalSignedPreKeyStore;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
const SignalSignedPreKeyStore *raw;
|
const SignalSignedPreKeyStore *raw;
|
||||||
|
|
@ -897,21 +871,23 @@ typedef struct {
|
||||||
SignalKyberPreKeyRecord *raw;
|
SignalKyberPreKeyRecord *raw;
|
||||||
} SignalMutPointerKyberPreKeyRecord;
|
} SignalMutPointerKyberPreKeyRecord;
|
||||||
|
|
||||||
typedef int (*SignalFfiKyberPreKeyStoreLoadKyberPreKey)(void *ctx, SignalMutPointerKyberPreKeyRecord *out, uint32_t id);
|
typedef int (*SignalFfiBridgeKyberPreKeyStoreLoadKyberPreKey)(void *ctx, SignalMutPointerKyberPreKeyRecord *out, uint32_t id);
|
||||||
|
|
||||||
typedef int (*SignalFfiKyberPreKeyStoreStoreKyberPreKey)(void *ctx, uint32_t id, SignalMutPointerKyberPreKeyRecord record);
|
typedef int (*SignalFfiBridgeKyberPreKeyStoreStoreKyberPreKey)(void *ctx, uint32_t id, SignalMutPointerKyberPreKeyRecord record);
|
||||||
|
|
||||||
typedef int (*SignalFfiKyberPreKeyStoreMarkKyberPreKeyUsed)(void *ctx, uint32_t id, uint32_t ec_prekey_id, SignalMutPointerPublicKey base_key);
|
typedef int (*SignalFfiBridgeKyberPreKeyStoreMarkKyberPreKeyUsed)(void *ctx, uint32_t id, uint32_t ec_prekey_id, SignalMutPointerPublicKey base_key);
|
||||||
|
|
||||||
typedef void (*SignalFfiKyberPreKeyStoreDestroy)(void *ctx);
|
typedef void (*SignalFfiBridgeKyberPreKeyStoreDestroy)(void *ctx);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
void *ctx;
|
void *ctx;
|
||||||
SignalFfiKyberPreKeyStoreLoadKyberPreKey load_kyber_pre_key;
|
SignalFfiBridgeKyberPreKeyStoreLoadKyberPreKey load_kyber_pre_key;
|
||||||
SignalFfiKyberPreKeyStoreStoreKyberPreKey store_kyber_pre_key;
|
SignalFfiBridgeKyberPreKeyStoreStoreKyberPreKey store_kyber_pre_key;
|
||||||
SignalFfiKyberPreKeyStoreMarkKyberPreKeyUsed mark_kyber_pre_key_used;
|
SignalFfiBridgeKyberPreKeyStoreMarkKyberPreKeyUsed mark_kyber_pre_key_used;
|
||||||
SignalFfiKyberPreKeyStoreDestroy destroy;
|
SignalFfiBridgeKyberPreKeyStoreDestroy destroy;
|
||||||
} SignalKyberPreKeyStore;
|
} SignalFfiBridgeKyberPreKeyStoreStruct;
|
||||||
|
|
||||||
|
typedef SignalFfiBridgeKyberPreKeyStoreStruct SignalKyberPreKeyStore;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
const SignalKyberPreKeyStore *raw;
|
const SignalKyberPreKeyStore *raw;
|
||||||
|
|
@ -969,11 +945,6 @@ typedef struct {
|
||||||
SignalOwnedBuffer second;
|
SignalOwnedBuffer second;
|
||||||
} SignalPairOfc_charOwnedBufferOfc_uchar;
|
} SignalPairOfc_charOwnedBufferOfc_uchar;
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
SignalPairOfc_charOwnedBufferOfc_uchar first;
|
|
||||||
int64_t second;
|
|
||||||
} SignalPairOfPairOfc_charOwnedBufferOfc_uchari64;
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
const char *first;
|
const char *first;
|
||||||
bool second;
|
bool second;
|
||||||
|
|
@ -1047,18 +1018,20 @@ typedef struct {
|
||||||
SignalSenderKeyRecord *raw;
|
SignalSenderKeyRecord *raw;
|
||||||
} SignalMutPointerSenderKeyRecord;
|
} SignalMutPointerSenderKeyRecord;
|
||||||
|
|
||||||
typedef int (*SignalFfiSenderKeyStoreLoadSenderKey)(void *ctx, SignalMutPointerSenderKeyRecord *out, SignalMutPointerProtocolAddress sender, SignalUuid distribution_id);
|
typedef int (*SignalFfiBridgeSenderKeyStoreLoadSenderKey)(void *ctx, SignalMutPointerSenderKeyRecord *out, SignalMutPointerProtocolAddress sender, SignalUuid distribution_id);
|
||||||
|
|
||||||
typedef int (*SignalFfiSenderKeyStoreStoreSenderKey)(void *ctx, SignalMutPointerProtocolAddress sender, SignalUuid distribution_id, SignalMutPointerSenderKeyRecord record);
|
typedef int (*SignalFfiBridgeSenderKeyStoreStoreSenderKey)(void *ctx, SignalMutPointerProtocolAddress sender, SignalUuid distribution_id, SignalMutPointerSenderKeyRecord record);
|
||||||
|
|
||||||
typedef void (*SignalFfiSenderKeyStoreDestroy)(void *ctx);
|
typedef void (*SignalFfiBridgeSenderKeyStoreDestroy)(void *ctx);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
void *ctx;
|
void *ctx;
|
||||||
SignalFfiSenderKeyStoreLoadSenderKey load_sender_key;
|
SignalFfiBridgeSenderKeyStoreLoadSenderKey load_sender_key;
|
||||||
SignalFfiSenderKeyStoreStoreSenderKey store_sender_key;
|
SignalFfiBridgeSenderKeyStoreStoreSenderKey store_sender_key;
|
||||||
SignalFfiSenderKeyStoreDestroy destroy;
|
SignalFfiBridgeSenderKeyStoreDestroy destroy;
|
||||||
} SignalSenderKeyStore;
|
} SignalFfiBridgeSenderKeyStoreStruct;
|
||||||
|
|
||||||
|
typedef SignalFfiBridgeSenderKeyStoreStruct SignalSenderKeyStore;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
const SignalSenderKeyStore *raw;
|
const SignalSenderKeyStore *raw;
|
||||||
|
|
@ -1102,23 +1075,15 @@ typedef struct {
|
||||||
SignalIncrementalMac *raw;
|
SignalIncrementalMac *raw;
|
||||||
} SignalMutPointerIncrementalMac;
|
} SignalMutPointerIncrementalMac;
|
||||||
|
|
||||||
typedef int (*SignalFfiLoggerLog)(void *ctx, SignalLogLevel level, const char *file, uint32_t line, const char *message);
|
typedef void (*SignalLogCallback)(void *ctx, SignalLogLevel level, const char *file, uint32_t line, const char *message);
|
||||||
|
|
||||||
typedef int (*SignalFfiLoggerFlush)(void *ctx);
|
typedef void (*SignalLogFlushCallback)(void *ctx);
|
||||||
|
|
||||||
typedef void (*SignalFfiLoggerDestroy)(void *ctx);
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
void *ctx;
|
void *ctx;
|
||||||
SignalFfiLoggerLog log;
|
SignalLogCallback log;
|
||||||
SignalFfiLoggerFlush flush;
|
SignalLogFlushCallback flush;
|
||||||
SignalFfiLoggerDestroy destroy;
|
} SignalFfiLogger;
|
||||||
} SignalFfiLoggerStruct;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
SignalOwnedBuffer first;
|
|
||||||
SignalOwnedBuffer second;
|
|
||||||
} SignalPairOfOwnedBufferOfc_ucharOwnedBufferOfc_uchar;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A C callback used to report the results of Rust futures.
|
* A C callback used to report the results of Rust futures.
|
||||||
|
|
@ -1130,10 +1095,10 @@ typedef struct {
|
||||||
* completed once.
|
* completed once.
|
||||||
*/
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
void (*complete)(SignalFfiError *error, const SignalPairOfOwnedBufferOfc_ucharOwnedBufferOfc_uchar *result, const void *context);
|
void (*complete)(SignalFfiError *error, const SignalOwnedBuffer *result, const void *context);
|
||||||
const void *context;
|
const void *context;
|
||||||
SignalCancellationId cancellation_id;
|
SignalCancellationId cancellation_id;
|
||||||
} SignalCPromisePairOfOwnedBufferOfc_ucharOwnedBufferOfc_uchar;
|
} SignalCPromiseOwnedBufferOfc_uchar;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
const SignalUnauthenticatedChatConnection *raw;
|
const SignalUnauthenticatedChatConnection *raw;
|
||||||
|
|
@ -1203,18 +1168,20 @@ typedef struct {
|
||||||
const SignalMessageBackupValidationOutcome *raw;
|
const SignalMessageBackupValidationOutcome *raw;
|
||||||
} SignalConstPointerMessageBackupValidationOutcome;
|
} SignalConstPointerMessageBackupValidationOutcome;
|
||||||
|
|
||||||
typedef int (*SignalFfiInputStreamRead)(void *ctx, size_t *out, SignalBorrowedMutableBuffer buf);
|
typedef int (*SignalFfiBridgeInputStreamRead)(void *ctx, size_t *out, SignalBorrowedMutableBuffer buf);
|
||||||
|
|
||||||
typedef int (*SignalFfiInputStreamSkip)(void *ctx, uint64_t amount);
|
typedef int (*SignalFfiBridgeInputStreamSkip)(void *ctx, uint64_t amount);
|
||||||
|
|
||||||
typedef void (*SignalFfiInputStreamDestroy)(void *ctx);
|
typedef void (*SignalFfiBridgeInputStreamDestroy)(void *ctx);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
void *ctx;
|
void *ctx;
|
||||||
SignalFfiInputStreamRead read;
|
SignalFfiBridgeInputStreamRead read;
|
||||||
SignalFfiInputStreamSkip skip;
|
SignalFfiBridgeInputStreamSkip skip;
|
||||||
SignalFfiInputStreamDestroy destroy;
|
SignalFfiBridgeInputStreamDestroy destroy;
|
||||||
} SignalInputStream;
|
} SignalFfiBridgeInputStreamStruct;
|
||||||
|
|
||||||
|
typedef SignalFfiBridgeInputStreamStruct SignalInputStream;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
const SignalInputStream *raw;
|
const SignalInputStream *raw;
|
||||||
|
|
@ -1648,7 +1615,9 @@ typedef struct {
|
||||||
SignalValidatingMac *raw;
|
SignalValidatingMac *raw;
|
||||||
} SignalMutPointerValidatingMac;
|
} SignalMutPointerValidatingMac;
|
||||||
|
|
||||||
typedef SignalInputStream SignalSyncInputStream;
|
typedef SignalFfiBridgeInputStreamStruct SignalFfiBridgeSyncInputStreamStruct;
|
||||||
|
|
||||||
|
typedef SignalFfiBridgeSyncInputStreamStruct SignalSyncInputStream;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
const SignalSyncInputStream *raw;
|
const SignalSyncInputStream *raw;
|
||||||
|
|
@ -1726,8 +1695,6 @@ SignalFfiError *signal_authenticated_chat_connection_destroy(SignalMutPointerAut
|
||||||
|
|
||||||
SignalFfiError *signal_authenticated_chat_connection_disconnect(SignalCPromisebool *promise, SignalConstPointerTokioAsyncContext async_runtime, SignalConstPointerAuthenticatedChatConnection chat);
|
SignalFfiError *signal_authenticated_chat_connection_disconnect(SignalCPromisebool *promise, SignalConstPointerTokioAsyncContext async_runtime, SignalConstPointerAuthenticatedChatConnection chat);
|
||||||
|
|
||||||
SignalFfiError *signal_authenticated_chat_connection_get_upload_form(SignalCPromiseFfiUploadForm *promise, SignalConstPointerTokioAsyncContext async_runtime, SignalConstPointerAuthenticatedChatConnection chat, uint64_t upload_length);
|
|
||||||
|
|
||||||
SignalFfiError *signal_authenticated_chat_connection_info(SignalMutPointerChatConnectionInfo *out, SignalConstPointerAuthenticatedChatConnection chat);
|
SignalFfiError *signal_authenticated_chat_connection_info(SignalMutPointerChatConnectionInfo *out, SignalConstPointerAuthenticatedChatConnection chat);
|
||||||
|
|
||||||
SignalFfiError *signal_authenticated_chat_connection_init_listener(SignalConstPointerAuthenticatedChatConnection chat, SignalConstPointerFfiChatListenerStruct listener);
|
SignalFfiError *signal_authenticated_chat_connection_init_listener(SignalConstPointerAuthenticatedChatConnection chat, SignalConstPointerFfiChatListenerStruct listener);
|
||||||
|
|
@ -1736,10 +1703,6 @@ SignalFfiError *signal_authenticated_chat_connection_preconnect(SignalCPromisebo
|
||||||
|
|
||||||
SignalFfiError *signal_authenticated_chat_connection_send(SignalCPromiseFfiChatResponse *promise, SignalConstPointerTokioAsyncContext async_runtime, SignalConstPointerAuthenticatedChatConnection chat, SignalConstPointerHttpRequest http_request, uint32_t timeout_millis);
|
SignalFfiError *signal_authenticated_chat_connection_send(SignalCPromiseFfiChatResponse *promise, SignalConstPointerTokioAsyncContext async_runtime, SignalConstPointerAuthenticatedChatConnection chat, SignalConstPointerHttpRequest http_request, uint32_t timeout_millis);
|
||||||
|
|
||||||
SignalFfiError *signal_authenticated_chat_connection_send_message(SignalCPromisebool *promise, SignalConstPointerTokioAsyncContext async_runtime, SignalConstPointerAuthenticatedChatConnection chat, const SignalServiceIdFixedWidthBinaryBytes *destination, uint64_t timestamp, SignalBorrowedSliceOfu32 device_ids, SignalBorrowedSliceOfu32 registration_ids, SignalBorrowedSliceOfConstPointerCiphertextMessage contents, bool online_only, bool is_urgent);
|
|
||||||
|
|
||||||
SignalFfiError *signal_authenticated_chat_connection_send_sync_message(SignalCPromisebool *promise, SignalConstPointerTokioAsyncContext async_runtime, SignalConstPointerAuthenticatedChatConnection chat, uint64_t timestamp, SignalBorrowedSliceOfu32 device_ids, SignalBorrowedSliceOfu32 registration_ids, SignalBorrowedSliceOfConstPointerCiphertextMessage contents, bool is_urgent);
|
|
||||||
|
|
||||||
SignalFfiError *signal_backup_auth_credential_check_valid_contents(SignalBorrowedBuffer params_bytes);
|
SignalFfiError *signal_backup_auth_credential_check_valid_contents(SignalBorrowedBuffer params_bytes);
|
||||||
|
|
||||||
SignalFfiError *signal_backup_auth_credential_get_backup_id(uint8_t (*out)[16], SignalBorrowedBuffer credential_bytes);
|
SignalFfiError *signal_backup_auth_credential_get_backup_id(uint8_t (*out)[16], SignalBorrowedBuffer credential_bytes);
|
||||||
|
|
@ -1900,9 +1863,9 @@ SignalFfiError *signal_create_call_link_credential_request_issue_deterministic(S
|
||||||
|
|
||||||
SignalFfiError *signal_create_call_link_credential_response_check_valid_contents(SignalBorrowedBuffer response_bytes);
|
SignalFfiError *signal_create_call_link_credential_response_check_valid_contents(SignalBorrowedBuffer response_bytes);
|
||||||
|
|
||||||
SignalFfiError *signal_decrypt_message(SignalOwnedBuffer *out, SignalConstPointerSignalMessage message, SignalConstPointerProtocolAddress protocol_address, SignalConstPointerProtocolAddress local_address, SignalConstPointerFfiSessionStoreStruct session_store, SignalConstPointerFfiIdentityKeyStoreStruct identity_key_store);
|
SignalFfiError *signal_decrypt_message(SignalOwnedBuffer *out, SignalConstPointerSignalMessage message, SignalConstPointerProtocolAddress protocol_address, SignalConstPointerFfiSessionStoreStruct session_store, SignalConstPointerFfiIdentityKeyStoreStruct identity_key_store);
|
||||||
|
|
||||||
SignalFfiError *signal_decrypt_pre_key_message(SignalOwnedBuffer *out, SignalConstPointerPreKeySignalMessage message, SignalConstPointerProtocolAddress protocol_address, SignalConstPointerProtocolAddress local_address, SignalConstPointerFfiSessionStoreStruct session_store, SignalConstPointerFfiIdentityKeyStoreStruct identity_key_store, SignalConstPointerFfiPreKeyStoreStruct prekey_store, SignalConstPointerFfiSignedPreKeyStoreStruct signed_prekey_store, SignalConstPointerFfiKyberPreKeyStoreStruct kyber_prekey_store);
|
SignalFfiError *signal_decrypt_pre_key_message(SignalOwnedBuffer *out, SignalConstPointerPreKeySignalMessage message, SignalConstPointerProtocolAddress protocol_address, SignalConstPointerFfiSessionStoreStruct session_store, SignalConstPointerFfiIdentityKeyStoreStruct identity_key_store, SignalConstPointerFfiPreKeyStoreStruct prekey_store, SignalConstPointerFfiSignedPreKeyStoreStruct signed_prekey_store, SignalConstPointerFfiKyberPreKeyStoreStruct kyber_prekey_store);
|
||||||
|
|
||||||
SignalFfiError *signal_decryption_error_message_clone(SignalMutPointerDecryptionErrorMessage *new_obj, SignalConstPointerDecryptionErrorMessage obj);
|
SignalFfiError *signal_decryption_error_message_clone(SignalMutPointerDecryptionErrorMessage *new_obj, SignalConstPointerDecryptionErrorMessage obj);
|
||||||
|
|
||||||
|
|
@ -1928,7 +1891,7 @@ SignalFfiError *signal_device_transfer_generate_private_key(SignalOwnedBuffer *o
|
||||||
|
|
||||||
SignalFfiError *signal_device_transfer_generate_private_key_with_format(SignalOwnedBuffer *out, uint8_t key_format);
|
SignalFfiError *signal_device_transfer_generate_private_key_with_format(SignalOwnedBuffer *out, uint8_t key_format);
|
||||||
|
|
||||||
SignalFfiError *signal_encrypt_message(SignalMutPointerCiphertextMessage *out, SignalBorrowedBuffer ptext, SignalConstPointerProtocolAddress protocol_address, SignalConstPointerProtocolAddress local_address, SignalConstPointerFfiSessionStoreStruct session_store, SignalConstPointerFfiIdentityKeyStoreStruct identity_key_store, uint64_t now);
|
SignalFfiError *signal_encrypt_message(SignalMutPointerCiphertextMessage *out, SignalBorrowedBuffer ptext, SignalConstPointerProtocolAddress protocol_address, SignalConstPointerFfiSessionStoreStruct session_store, SignalConstPointerFfiIdentityKeyStoreStruct identity_key_store, uint64_t now);
|
||||||
|
|
||||||
void signal_error_free(SignalFfiError *err);
|
void signal_error_free(SignalFfiError *err);
|
||||||
|
|
||||||
|
|
@ -1942,7 +1905,7 @@ SignalFfiError *signal_error_get_mismatched_device_errors(SignalOwnedBufferOfFfi
|
||||||
|
|
||||||
SignalFfiError *signal_error_get_our_fingerprint_version(uint32_t *out, SignalUnwindSafeArgSignalFfiError err);
|
SignalFfiError *signal_error_get_our_fingerprint_version(uint32_t *out, SignalUnwindSafeArgSignalFfiError err);
|
||||||
|
|
||||||
SignalFfiError *signal_error_get_rate_limit_challenge(SignalPairOfPairOfc_charOwnedBufferOfc_uchari64 *out, SignalUnwindSafeArgSignalFfiError err);
|
SignalFfiError *signal_error_get_rate_limit_challenge(SignalPairOfc_charOwnedBufferOfc_uchar *out, SignalUnwindSafeArgSignalFfiError err);
|
||||||
|
|
||||||
SignalFfiError *signal_error_get_registration_error_not_deliverable(SignalPairOfc_charbool *out, SignalUnwindSafeArgSignalFfiError err);
|
SignalFfiError *signal_error_get_registration_error_not_deliverable(SignalPairOfc_charbool *out, SignalUnwindSafeArgSignalFfiError err);
|
||||||
|
|
||||||
|
|
@ -2117,14 +2080,18 @@ SignalFfiError *signal_incremental_mac_initialize(SignalMutPointerIncrementalMac
|
||||||
|
|
||||||
SignalFfiError *signal_incremental_mac_update(SignalOwnedBuffer *out, SignalMutPointerIncrementalMac mac, SignalBorrowedBuffer bytes, uint32_t offset, uint32_t length);
|
SignalFfiError *signal_incremental_mac_update(SignalOwnedBuffer *out, SignalMutPointerIncrementalMac mac, SignalBorrowedBuffer bytes, uint32_t offset, uint32_t length);
|
||||||
|
|
||||||
bool signal_init_logger(SignalLogLevel max_level, SignalFfiLoggerStruct logger);
|
bool signal_init_logger(SignalLogLevel max_level, SignalFfiLogger logger);
|
||||||
|
|
||||||
SignalFfiError *signal_key_transparency_aci_search_key(SignalOwnedBuffer *out, const SignalServiceIdFixedWidthBinaryBytes *aci);
|
SignalFfiError *signal_key_transparency_aci_search_key(SignalOwnedBuffer *out, const SignalServiceIdFixedWidthBinaryBytes *aci);
|
||||||
|
|
||||||
SignalFfiError *signal_key_transparency_check(SignalCPromisePairOfOwnedBufferOfc_ucharOwnedBufferOfc_uchar *promise, SignalConstPointerTokioAsyncContext async_runtime, uint8_t environment, SignalConstPointerUnauthenticatedChatConnection chat_connection, const SignalServiceIdFixedWidthBinaryBytes *aci, SignalConstPointerPublicKey aci_identity_key, const char *e164, SignalOptionalBorrowedSliceOfc_uchar unidentified_access_key, SignalOptionalBorrowedSliceOfc_uchar username_hash, SignalOptionalBorrowedSliceOfc_uchar account_data, SignalOptionalBorrowedSliceOfc_uchar last_distinguished_tree_head, bool is_self_check, bool is_e164_discoverable);
|
SignalFfiError *signal_key_transparency_distinguished(SignalCPromiseOwnedBufferOfc_uchar *promise, SignalConstPointerTokioAsyncContext async_runtime, uint8_t environment, SignalConstPointerUnauthenticatedChatConnection chat_connection, SignalOptionalBorrowedSliceOfc_uchar last_distinguished_tree_head);
|
||||||
|
|
||||||
SignalFfiError *signal_key_transparency_e164_search_key(SignalOwnedBuffer *out, const char *e164);
|
SignalFfiError *signal_key_transparency_e164_search_key(SignalOwnedBuffer *out, const char *e164);
|
||||||
|
|
||||||
|
SignalFfiError *signal_key_transparency_monitor(SignalCPromiseOwnedBufferOfc_uchar *promise, SignalConstPointerTokioAsyncContext async_runtime, uint8_t environment, SignalConstPointerUnauthenticatedChatConnection chat_connection, const SignalServiceIdFixedWidthBinaryBytes *aci, SignalConstPointerPublicKey aci_identity_key, const char *e164, SignalOptionalBorrowedSliceOfc_uchar unidentified_access_key, SignalOptionalBorrowedSliceOfc_uchar username_hash, SignalOptionalBorrowedSliceOfc_uchar account_data, SignalBorrowedBuffer last_distinguished_tree_head, bool is_self_monitor);
|
||||||
|
|
||||||
|
SignalFfiError *signal_key_transparency_search(SignalCPromiseOwnedBufferOfc_uchar *promise, SignalConstPointerTokioAsyncContext async_runtime, uint8_t environment, SignalConstPointerUnauthenticatedChatConnection chat_connection, const SignalServiceIdFixedWidthBinaryBytes *aci, SignalConstPointerPublicKey aci_identity_key, const char *e164, SignalOptionalBorrowedSliceOfc_uchar unidentified_access_key, SignalOptionalBorrowedSliceOfc_uchar username_hash, SignalOptionalBorrowedSliceOfc_uchar account_data, SignalBorrowedBuffer last_distinguished_tree_head);
|
||||||
|
|
||||||
SignalFfiError *signal_key_transparency_username_hash_search_key(SignalOwnedBuffer *out, SignalBorrowedBuffer hash);
|
SignalFfiError *signal_key_transparency_username_hash_search_key(SignalOwnedBuffer *out, SignalBorrowedBuffer hash);
|
||||||
|
|
||||||
SignalFfiError *signal_kyber_key_pair_clone(SignalMutPointerKyberKeyPair *new_obj, SignalConstPointerKyberKeyPair obj);
|
SignalFfiError *signal_kyber_key_pair_clone(SignalMutPointerKyberKeyPair *new_obj, SignalConstPointerKyberKeyPair obj);
|
||||||
|
|
@ -2355,7 +2322,7 @@ SignalFfiError *signal_privatekey_serialize(SignalOwnedBuffer *out, SignalConstP
|
||||||
|
|
||||||
SignalFfiError *signal_privatekey_sign(SignalOwnedBuffer *out, SignalConstPointerPrivateKey key, SignalBorrowedBuffer message);
|
SignalFfiError *signal_privatekey_sign(SignalOwnedBuffer *out, SignalConstPointerPrivateKey key, SignalBorrowedBuffer message);
|
||||||
|
|
||||||
SignalFfiError *signal_process_prekey_bundle(SignalConstPointerPreKeyBundle bundle, SignalConstPointerProtocolAddress protocol_address, SignalConstPointerProtocolAddress local_address, SignalConstPointerFfiSessionStoreStruct session_store, SignalConstPointerFfiIdentityKeyStoreStruct identity_key_store, uint64_t now);
|
SignalFfiError *signal_process_prekey_bundle(SignalConstPointerPreKeyBundle bundle, SignalConstPointerProtocolAddress protocol_address, SignalConstPointerFfiSessionStoreStruct session_store, SignalConstPointerFfiIdentityKeyStoreStruct identity_key_store, uint64_t now);
|
||||||
|
|
||||||
SignalFfiError *signal_process_sender_key_distribution_message(SignalConstPointerProtocolAddress sender, SignalConstPointerSenderKeyDistributionMessage sender_key_distribution_message, SignalConstPointerFfiSenderKeyStoreStruct store);
|
SignalFfiError *signal_process_sender_key_distribution_message(SignalConstPointerProtocolAddress sender, SignalConstPointerSenderKeyDistributionMessage sender_key_distribution_message, SignalConstPointerFfiSenderKeyStoreStruct store);
|
||||||
|
|
||||||
|
|
@ -2757,22 +2724,16 @@ SignalFfiError *signal_tokio_async_context_new(SignalMutPointerTokioAsyncContext
|
||||||
|
|
||||||
SignalFfiError *signal_unauthenticated_chat_connection_account_exists(SignalCPromisebool *promise, SignalConstPointerTokioAsyncContext async_runtime, SignalConstPointerUnauthenticatedChatConnection chat, const SignalServiceIdFixedWidthBinaryBytes *account);
|
SignalFfiError *signal_unauthenticated_chat_connection_account_exists(SignalCPromisebool *promise, SignalConstPointerTokioAsyncContext async_runtime, SignalConstPointerUnauthenticatedChatConnection chat, const SignalServiceIdFixedWidthBinaryBytes *account);
|
||||||
|
|
||||||
SignalFfiError *signal_unauthenticated_chat_connection_backup_get_media_upload_form(SignalCPromiseFfiUploadForm *promise, SignalConstPointerTokioAsyncContext async_runtime, SignalConstPointerUnauthenticatedChatConnection chat, SignalBorrowedBuffer credential, SignalBorrowedBuffer server_keys, SignalConstPointerPrivateKey signing_key, uint64_t upload_size, int64_t rng);
|
|
||||||
|
|
||||||
SignalFfiError *signal_unauthenticated_chat_connection_backup_get_upload_form(SignalCPromiseFfiUploadForm *promise, SignalConstPointerTokioAsyncContext async_runtime, SignalConstPointerUnauthenticatedChatConnection chat, SignalBorrowedBuffer credential, SignalBorrowedBuffer server_keys, SignalConstPointerPrivateKey signing_key, uint64_t upload_size, int64_t rng);
|
|
||||||
|
|
||||||
SignalFfiError *signal_unauthenticated_chat_connection_connect(SignalCPromiseMutPointerUnauthenticatedChatConnection *promise, SignalConstPointerTokioAsyncContext async_runtime, SignalConstPointerConnectionManager connection_manager, SignalBorrowedBytestringArray languages);
|
SignalFfiError *signal_unauthenticated_chat_connection_connect(SignalCPromiseMutPointerUnauthenticatedChatConnection *promise, SignalConstPointerTokioAsyncContext async_runtime, SignalConstPointerConnectionManager connection_manager, SignalBorrowedBytestringArray languages);
|
||||||
|
|
||||||
SignalFfiError *signal_unauthenticated_chat_connection_destroy(SignalMutPointerUnauthenticatedChatConnection p);
|
SignalFfiError *signal_unauthenticated_chat_connection_destroy(SignalMutPointerUnauthenticatedChatConnection p);
|
||||||
|
|
||||||
SignalFfiError *signal_unauthenticated_chat_connection_disconnect(SignalCPromisebool *promise, SignalConstPointerTokioAsyncContext async_runtime, SignalConstPointerUnauthenticatedChatConnection chat);
|
SignalFfiError *signal_unauthenticated_chat_connection_disconnect(SignalCPromisebool *promise, SignalConstPointerTokioAsyncContext async_runtime, SignalConstPointerUnauthenticatedChatConnection chat);
|
||||||
|
|
||||||
|
SignalFfiError *signal_unauthenticated_chat_connection_get_pre_keys_access_group_auth(SignalCPromiseFfiPreKeysResponse *promise, SignalConstPointerTokioAsyncContext async_runtime, SignalConstPointerUnauthenticatedChatConnection chat, SignalBorrowedBuffer auth, const SignalServiceIdFixedWidthBinaryBytes *target, int32_t device);
|
||||||
|
|
||||||
SignalFfiError *signal_unauthenticated_chat_connection_get_pre_keys_access_key_auth(SignalCPromiseFfiPreKeysResponse *promise, SignalConstPointerTokioAsyncContext async_runtime, SignalConstPointerUnauthenticatedChatConnection chat, const uint8_t (*auth)[16], const SignalServiceIdFixedWidthBinaryBytes *target, int32_t device);
|
SignalFfiError *signal_unauthenticated_chat_connection_get_pre_keys_access_key_auth(SignalCPromiseFfiPreKeysResponse *promise, SignalConstPointerTokioAsyncContext async_runtime, SignalConstPointerUnauthenticatedChatConnection chat, const uint8_t (*auth)[16], const SignalServiceIdFixedWidthBinaryBytes *target, int32_t device);
|
||||||
|
|
||||||
SignalFfiError *signal_unauthenticated_chat_connection_get_pre_keys_group_auth(SignalCPromiseFfiPreKeysResponse *promise, SignalConstPointerTokioAsyncContext async_runtime, SignalConstPointerUnauthenticatedChatConnection chat, SignalBorrowedBuffer auth, const SignalServiceIdFixedWidthBinaryBytes *target, int32_t device);
|
|
||||||
|
|
||||||
SignalFfiError *signal_unauthenticated_chat_connection_get_pre_keys_unrestricted_auth(SignalCPromiseFfiPreKeysResponse *promise, SignalConstPointerTokioAsyncContext async_runtime, SignalConstPointerUnauthenticatedChatConnection chat, const SignalServiceIdFixedWidthBinaryBytes *target, int32_t device);
|
|
||||||
|
|
||||||
SignalFfiError *signal_unauthenticated_chat_connection_info(SignalMutPointerChatConnectionInfo *out, SignalConstPointerUnauthenticatedChatConnection chat);
|
SignalFfiError *signal_unauthenticated_chat_connection_info(SignalMutPointerChatConnectionInfo *out, SignalConstPointerUnauthenticatedChatConnection chat);
|
||||||
|
|
||||||
SignalFfiError *signal_unauthenticated_chat_connection_init_listener(SignalConstPointerUnauthenticatedChatConnection chat, SignalConstPointerFfiChatListenerStruct listener);
|
SignalFfiError *signal_unauthenticated_chat_connection_init_listener(SignalConstPointerUnauthenticatedChatConnection chat, SignalConstPointerFfiChatListenerStruct listener);
|
||||||
|
|
@ -2783,8 +2744,6 @@ SignalFfiError *signal_unauthenticated_chat_connection_look_up_username_link(Sig
|
||||||
|
|
||||||
SignalFfiError *signal_unauthenticated_chat_connection_send(SignalCPromiseFfiChatResponse *promise, SignalConstPointerTokioAsyncContext async_runtime, SignalConstPointerUnauthenticatedChatConnection chat, SignalConstPointerHttpRequest http_request, uint32_t timeout_millis);
|
SignalFfiError *signal_unauthenticated_chat_connection_send(SignalCPromiseFfiChatResponse *promise, SignalConstPointerTokioAsyncContext async_runtime, SignalConstPointerUnauthenticatedChatConnection chat, SignalConstPointerHttpRequest http_request, uint32_t timeout_millis);
|
||||||
|
|
||||||
SignalFfiError *signal_unauthenticated_chat_connection_send_message(SignalCPromisebool *promise, SignalConstPointerTokioAsyncContext async_runtime, SignalConstPointerUnauthenticatedChatConnection chat, const SignalServiceIdFixedWidthBinaryBytes *destination, uint64_t timestamp, SignalBorrowedSliceOfu32 device_ids, SignalBorrowedSliceOfu32 registration_ids, SignalBorrowedSliceOfBuffers contents, uint8_t auth_kind, SignalOptionalBorrowedSliceOfc_uchar auth_buffer, bool online_only, bool is_urgent);
|
|
||||||
|
|
||||||
SignalFfiError *signal_unauthenticated_chat_connection_send_multi_recipient_message(SignalCPromiseOwnedBufferOfServiceIdFixedWidthBinaryBytes *promise, SignalConstPointerTokioAsyncContext async_runtime, SignalConstPointerUnauthenticatedChatConnection chat, SignalBorrowedBuffer payload, uint64_t timestamp, SignalBorrowedBuffer auth, bool online_only, bool is_urgent);
|
SignalFfiError *signal_unauthenticated_chat_connection_send_multi_recipient_message(SignalCPromiseOwnedBufferOfServiceIdFixedWidthBinaryBytes *promise, SignalConstPointerTokioAsyncContext async_runtime, SignalConstPointerUnauthenticatedChatConnection chat, SignalBorrowedBuffer payload, uint64_t timestamp, SignalBorrowedBuffer auth, bool online_only, bool is_urgent);
|
||||||
|
|
||||||
SignalFfiError *signal_unidentified_sender_message_content_deserialize(SignalMutPointerUnidentifiedSenderMessageContent *out, SignalBorrowedBuffer data);
|
SignalFfiError *signal_unidentified_sender_message_content_deserialize(SignalMutPointerUnidentifiedSenderMessageContent *out, SignalBorrowedBuffer data);
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,6 @@ package libsignalgo
|
||||||
|
|
||||||
extern void signal_log_callback(void *ctx, SignalLogLevel level, char *file, uint32_t line, char *message);
|
extern void signal_log_callback(void *ctx, SignalLogLevel level, char *file, uint32_t line, char *message);
|
||||||
extern void signal_log_flush_callback(void *ctx);
|
extern void signal_log_flush_callback(void *ctx);
|
||||||
extern void signal_log_destroy_callback(void *ctx);
|
|
||||||
*/
|
*/
|
||||||
import "C"
|
import "C"
|
||||||
import (
|
import (
|
||||||
|
|
@ -41,11 +40,6 @@ func signal_log_flush_callback(ctx unsafe.Pointer) {
|
||||||
ffiLogger.Flush()
|
ffiLogger.Flush()
|
||||||
}
|
}
|
||||||
|
|
||||||
//export signal_log_destroy_callback
|
|
||||||
func signal_log_destroy_callback(ctx unsafe.Pointer) {
|
|
||||||
ffiLogger.Destroy()
|
|
||||||
}
|
|
||||||
|
|
||||||
type LogLevel int
|
type LogLevel int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
@ -59,14 +53,12 @@ const (
|
||||||
type Logger interface {
|
type Logger interface {
|
||||||
Log(level LogLevel, file string, line uint, message string)
|
Log(level LogLevel, file string, line uint, message string)
|
||||||
Flush()
|
Flush()
|
||||||
Destroy()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func InitLogger(level LogLevel, logger Logger) {
|
func InitLogger(level LogLevel, logger Logger) {
|
||||||
ffiLogger = logger
|
ffiLogger = logger
|
||||||
C.signal_init_logger(C.SignalLogLevel(level), C.SignalFfiLoggerStruct{
|
C.signal_init_logger(C.SignalLogLevel(level), C.SignalFfiLogger{
|
||||||
log: C.SignalFfiLoggerLog(C.signal_log_callback),
|
log: C.SignalLogCallback(C.signal_log_callback),
|
||||||
flush: C.SignalFfiLoggerFlush(C.signal_log_flush_callback),
|
flush: C.SignalLogFlushCallback(C.signal_log_flush_callback),
|
||||||
destroy: C.SignalFfiLoggerDestroy(C.signal_log_destroy_callback),
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Encrypt(ctx context.Context, plaintext []byte, forAddress, localAddress *Address, sessionStore SessionStore, identityKeyStore IdentityKeyStore) (*CiphertextMessage, error) {
|
func Encrypt(ctx context.Context, plaintext []byte, forAddress *Address, sessionStore SessionStore, identityKeyStore IdentityKeyStore) (*CiphertextMessage, error) {
|
||||||
var ciphertextMessage C.SignalMutPointerCiphertextMessage
|
var ciphertextMessage C.SignalMutPointerCiphertextMessage
|
||||||
var now C.uint64_t = C.uint64_t(time.Now().Unix())
|
var now C.uint64_t = C.uint64_t(time.Now().Unix())
|
||||||
callbackCtx := NewCallbackContext(ctx)
|
callbackCtx := NewCallbackContext(ctx)
|
||||||
|
|
@ -36,7 +36,6 @@ func Encrypt(ctx context.Context, plaintext []byte, forAddress, localAddress *Ad
|
||||||
&ciphertextMessage,
|
&ciphertextMessage,
|
||||||
BytesToBuffer(plaintext),
|
BytesToBuffer(plaintext),
|
||||||
forAddress.constPtr(),
|
forAddress.constPtr(),
|
||||||
localAddress.constPtr(),
|
|
||||||
callbackCtx.wrapSessionStore(sessionStore),
|
callbackCtx.wrapSessionStore(sessionStore),
|
||||||
callbackCtx.wrapIdentityKeyStore(identityKeyStore),
|
callbackCtx.wrapIdentityKeyStore(identityKeyStore),
|
||||||
now,
|
now,
|
||||||
|
|
@ -49,7 +48,7 @@ func Encrypt(ctx context.Context, plaintext []byte, forAddress, localAddress *Ad
|
||||||
return wrapCiphertextMessage(ciphertextMessage.raw), nil
|
return wrapCiphertextMessage(ciphertextMessage.raw), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func Decrypt(ctx context.Context, message *Message, fromAddress, localAddress *Address, sessionStore SessionStore, identityStore IdentityKeyStore) ([]byte, error) {
|
func Decrypt(ctx context.Context, message *Message, fromAddress *Address, sessionStore SessionStore, identityStore IdentityKeyStore) ([]byte, error) {
|
||||||
callbackCtx := NewCallbackContext(ctx)
|
callbackCtx := NewCallbackContext(ctx)
|
||||||
defer callbackCtx.Unref()
|
defer callbackCtx.Unref()
|
||||||
var decrypted C.SignalOwnedBuffer = C.SignalOwnedBuffer{}
|
var decrypted C.SignalOwnedBuffer = C.SignalOwnedBuffer{}
|
||||||
|
|
@ -57,7 +56,6 @@ func Decrypt(ctx context.Context, message *Message, fromAddress, localAddress *A
|
||||||
&decrypted,
|
&decrypted,
|
||||||
message.constPtr(),
|
message.constPtr(),
|
||||||
fromAddress.constPtr(),
|
fromAddress.constPtr(),
|
||||||
localAddress.constPtr(),
|
|
||||||
callbackCtx.wrapSessionStore(sessionStore),
|
callbackCtx.wrapSessionStore(sessionStore),
|
||||||
callbackCtx.wrapIdentityKeyStore(identityStore),
|
callbackCtx.wrapIdentityKeyStore(identityStore),
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ import (
|
||||||
"runtime"
|
"runtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
func DecryptPreKey(ctx context.Context, preKeyMessage *PreKeyMessage, fromAddress, localAddress *Address, sessionStore SessionStore, identityStore IdentityKeyStore, preKeyStore PreKeyStore, signedPreKeyStore SignedPreKeyStore, kyberPreKeyStore KyberPreKeyStore) ([]byte, error) {
|
func DecryptPreKey(ctx context.Context, preKeyMessage *PreKeyMessage, fromAddress *Address, sessionStore SessionStore, identityStore IdentityKeyStore, preKeyStore PreKeyStore, signedPreKeyStore SignedPreKeyStore, kyberPreKeyStore KyberPreKeyStore) ([]byte, error) {
|
||||||
callbackCtx := NewCallbackContext(ctx)
|
callbackCtx := NewCallbackContext(ctx)
|
||||||
defer callbackCtx.Unref()
|
defer callbackCtx.Unref()
|
||||||
var decrypted C.SignalOwnedBuffer = C.SignalOwnedBuffer{}
|
var decrypted C.SignalOwnedBuffer = C.SignalOwnedBuffer{}
|
||||||
|
|
@ -34,7 +34,6 @@ func DecryptPreKey(ctx context.Context, preKeyMessage *PreKeyMessage, fromAddres
|
||||||
&decrypted,
|
&decrypted,
|
||||||
preKeyMessage.constPtr(),
|
preKeyMessage.constPtr(),
|
||||||
fromAddress.constPtr(),
|
fromAddress.constPtr(),
|
||||||
localAddress.constPtr(),
|
|
||||||
callbackCtx.wrapSessionStore(sessionStore),
|
callbackCtx.wrapSessionStore(sessionStore),
|
||||||
callbackCtx.wrapIdentityKeyStore(identityStore),
|
callbackCtx.wrapIdentityKeyStore(identityStore),
|
||||||
callbackCtx.wrapPreKeyStore(preKeyStore),
|
callbackCtx.wrapPreKeyStore(preKeyStore),
|
||||||
|
|
|
||||||
|
|
@ -27,14 +27,13 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func ProcessPreKeyBundle(ctx context.Context, bundle *PreKeyBundle, forAddress, localAddress *Address, sessionStore SessionStore, identityStore IdentityKeyStore) error {
|
func ProcessPreKeyBundle(ctx context.Context, bundle *PreKeyBundle, forAddress *Address, sessionStore SessionStore, identityStore IdentityKeyStore) error {
|
||||||
callbackCtx := NewCallbackContext(ctx)
|
callbackCtx := NewCallbackContext(ctx)
|
||||||
defer callbackCtx.Unref()
|
defer callbackCtx.Unref()
|
||||||
var now C.uint64_t = C.uint64_t(time.Now().Unix())
|
var now C.uint64_t = C.uint64_t(time.Now().Unix())
|
||||||
signalFfiError := C.signal_process_prekey_bundle(
|
signalFfiError := C.signal_process_prekey_bundle(
|
||||||
bundle.constPtr(),
|
bundle.constPtr(),
|
||||||
forAddress.constPtr(),
|
forAddress.constPtr(),
|
||||||
localAddress.constPtr(),
|
|
||||||
callbackCtx.wrapSessionStore(sessionStore),
|
callbackCtx.wrapSessionStore(sessionStore),
|
||||||
callbackCtx.wrapIdentityKeyStore(identityStore),
|
callbackCtx.wrapIdentityKeyStore(identityStore),
|
||||||
now,
|
now,
|
||||||
|
|
|
||||||
|
|
@ -76,9 +76,9 @@ func signal_destroy_pre_key_store_callback(storeCtx unsafe.Pointer) {
|
||||||
func (ctx *CallbackContext) wrapPreKeyStore(store PreKeyStore) C.SignalConstPointerFfiPreKeyStoreStruct {
|
func (ctx *CallbackContext) wrapPreKeyStore(store PreKeyStore) C.SignalConstPointerFfiPreKeyStoreStruct {
|
||||||
return C.SignalConstPointerFfiPreKeyStoreStruct{&C.SignalPreKeyStore{
|
return C.SignalConstPointerFfiPreKeyStoreStruct{&C.SignalPreKeyStore{
|
||||||
ctx: wrapStore(ctx, store),
|
ctx: wrapStore(ctx, store),
|
||||||
load_pre_key: C.SignalFfiPreKeyStoreLoadPreKey(C.signal_load_pre_key_callback),
|
load_pre_key: C.SignalFfiBridgePreKeyStoreLoadPreKey(C.signal_load_pre_key_callback),
|
||||||
store_pre_key: C.SignalFfiPreKeyStoreStorePreKey(C.signal_store_pre_key_callback),
|
store_pre_key: C.SignalFfiBridgePreKeyStoreStorePreKey(C.signal_store_pre_key_callback),
|
||||||
remove_pre_key: C.SignalFfiPreKeyStoreRemovePreKey(C.signal_remove_pre_key_callback),
|
remove_pre_key: C.SignalFfiBridgePreKeyStoreRemovePreKey(C.signal_remove_pre_key_callback),
|
||||||
destroy: C.SignalFfiPreKeyStoreDestroy(C.signal_destroy_pre_key_store_callback),
|
destroy: C.SignalFfiBridgePreKeyStoreDestroy(C.signal_destroy_pre_key_store_callback),
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -44,17 +44,8 @@ func NewSealedSenderAddress(e164 string, uuid uuid.UUID, deviceID uint32) *Seale
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func SealedSenderEncryptPlaintext(
|
func SealedSenderEncryptPlaintext(ctx context.Context, message []byte, contentHint UnidentifiedSenderMessageContentHint, forAddress *Address, fromSenderCert *SenderCertificate, sessionStore SessionStore, identityStore IdentityKeyStore, groupID *GroupIdentifier) ([]byte, error) {
|
||||||
ctx context.Context,
|
ciphertextMessage, err := Encrypt(ctx, message, forAddress, sessionStore, identityStore)
|
||||||
message []byte,
|
|
||||||
contentHint UnidentifiedSenderMessageContentHint,
|
|
||||||
forAddress, localAddress *Address,
|
|
||||||
fromSenderCert *SenderCertificate,
|
|
||||||
sessionStore SessionStore,
|
|
||||||
identityStore IdentityKeyStore,
|
|
||||||
groupID *GroupIdentifier,
|
|
||||||
) ([]byte, error) {
|
|
||||||
ciphertextMessage, err := Encrypt(ctx, message, forAddress, localAddress, sessionStore, identityStore)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -70,8 +70,8 @@ func signal_destroy_sender_key_store_callback(storeCtx unsafe.Pointer) {
|
||||||
func (ctx *CallbackContext) wrapSenderKeyStore(store SenderKeyStore) C.SignalConstPointerFfiSenderKeyStoreStruct {
|
func (ctx *CallbackContext) wrapSenderKeyStore(store SenderKeyStore) C.SignalConstPointerFfiSenderKeyStoreStruct {
|
||||||
return C.SignalConstPointerFfiSenderKeyStoreStruct{&C.SignalSenderKeyStore{
|
return C.SignalConstPointerFfiSenderKeyStoreStruct{&C.SignalSenderKeyStore{
|
||||||
ctx: wrapStore(ctx, store),
|
ctx: wrapStore(ctx, store),
|
||||||
load_sender_key: C.SignalFfiSenderKeyStoreLoadSenderKey(C.signal_load_sender_key_callback),
|
load_sender_key: C.SignalFfiBridgeSenderKeyStoreLoadSenderKey(C.signal_load_sender_key_callback),
|
||||||
store_sender_key: C.SignalFfiSenderKeyStoreStoreSenderKey(C.signal_store_sender_key_callback),
|
store_sender_key: C.SignalFfiBridgeSenderKeyStoreStoreSenderKey(C.signal_store_sender_key_callback),
|
||||||
destroy: C.SignalFfiSenderKeyStoreDestroy(C.signal_destroy_sender_key_store_callback),
|
destroy: C.SignalFfiBridgeSenderKeyStoreDestroy(C.signal_destroy_sender_key_store_callback),
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ import (
|
||||||
"go.mau.fi/mautrix-signal/pkg/libsignalgo"
|
"go.mau.fi/mautrix-signal/pkg/libsignalgo"
|
||||||
)
|
)
|
||||||
|
|
||||||
func initializeSessions(t *testing.T, aliceStore, bobStore *InMemorySignalProtocolStore, bobAddress, aliceAddress *libsignalgo.Address) {
|
func initializeSessions(t *testing.T, aliceStore, bobStore *InMemorySignalProtocolStore, bobAddress *libsignalgo.Address) {
|
||||||
ctx := context.TODO()
|
ctx := context.TODO()
|
||||||
|
|
||||||
bobPreKey, err := libsignalgo.GeneratePrivateKey()
|
bobPreKey, err := libsignalgo.GeneratePrivateKey()
|
||||||
|
|
@ -86,7 +86,7 @@ func initializeSessions(t *testing.T, aliceStore, bobStore *InMemorySignalProtoc
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
// Alice processes the bundle
|
// Alice processes the bundle
|
||||||
err = libsignalgo.ProcessPreKeyBundle(ctx, bobBundle, bobAddress, aliceAddress, aliceStore, aliceStore)
|
err = libsignalgo.ProcessPreKeyBundle(ctx, bobBundle, bobAddress, aliceStore, aliceStore)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
record, err := aliceStore.LoadSession(ctx, bobAddress)
|
record, err := aliceStore.LoadSession(ctx, bobAddress)
|
||||||
|
|
@ -132,11 +132,11 @@ func TestSessionCipher(t *testing.T) {
|
||||||
aliceStore := NewInMemorySignalProtocolStore()
|
aliceStore := NewInMemorySignalProtocolStore()
|
||||||
bobStore := NewInMemorySignalProtocolStore()
|
bobStore := NewInMemorySignalProtocolStore()
|
||||||
|
|
||||||
initializeSessions(t, aliceStore, bobStore, bobAddress, aliceAddress)
|
initializeSessions(t, aliceStore, bobStore, bobAddress)
|
||||||
|
|
||||||
alicePlaintext := []byte{8, 6, 7, 5, 3, 0, 9}
|
alicePlaintext := []byte{8, 6, 7, 5, 3, 0, 9}
|
||||||
|
|
||||||
aliceCiphertext, err := libsignalgo.Encrypt(ctx, alicePlaintext, bobAddress, aliceAddress, aliceStore, aliceStore)
|
aliceCiphertext, err := libsignalgo.Encrypt(ctx, alicePlaintext, bobAddress, aliceStore, aliceStore)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
aliceCiphertextMessageType, err := aliceCiphertext.MessageType()
|
aliceCiphertextMessageType, err := aliceCiphertext.MessageType()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
@ -147,13 +147,13 @@ func TestSessionCipher(t *testing.T) {
|
||||||
bobCiphertext, err := libsignalgo.DeserializePreKeyMessage(aliceCiphertextSerialized)
|
bobCiphertext, err := libsignalgo.DeserializePreKeyMessage(aliceCiphertextSerialized)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
bobPlaintext, err := libsignalgo.DecryptPreKey(ctx, bobCiphertext, aliceAddress, bobAddress, bobStore, bobStore, bobStore, bobStore, bobStore)
|
bobPlaintext, err := libsignalgo.DecryptPreKey(ctx, bobCiphertext, aliceAddress, bobStore, bobStore, bobStore, bobStore, bobStore)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, alicePlaintext, bobPlaintext)
|
assert.Equal(t, alicePlaintext, bobPlaintext)
|
||||||
|
|
||||||
bobPlaintext2 := []byte{23}
|
bobPlaintext2 := []byte{23}
|
||||||
|
|
||||||
bobCiphertext2, err := libsignalgo.Encrypt(ctx, bobPlaintext2, aliceAddress, bobAddress, bobStore, bobStore)
|
bobCiphertext2, err := libsignalgo.Encrypt(ctx, bobPlaintext2, aliceAddress, bobStore, bobStore)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
bobCiphertext2MessageType, err := bobCiphertext2.MessageType()
|
bobCiphertext2MessageType, err := bobCiphertext2.MessageType()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
@ -163,7 +163,7 @@ func TestSessionCipher(t *testing.T) {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
aliceCiphertext2, err := libsignalgo.DeserializeMessage(bobCiphertext2Serialized)
|
aliceCiphertext2, err := libsignalgo.DeserializeMessage(bobCiphertext2Serialized)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
alicePlaintext2, err := libsignalgo.Decrypt(ctx, aliceCiphertext2, bobAddress, aliceAddress, aliceStore, aliceStore)
|
alicePlaintext2, err := libsignalgo.Decrypt(ctx, aliceCiphertext2, bobAddress, aliceStore, aliceStore)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, bobPlaintext2, alicePlaintext2)
|
assert.Equal(t, bobPlaintext2, alicePlaintext2)
|
||||||
}
|
}
|
||||||
|
|
@ -183,11 +183,11 @@ func TestSessionCipherWithBadStore(t *testing.T) {
|
||||||
aliceStore := NewInMemorySignalProtocolStore()
|
aliceStore := NewInMemorySignalProtocolStore()
|
||||||
bobStore := &BadInMemorySignalProtocolStore{NewInMemorySignalProtocolStore()}
|
bobStore := &BadInMemorySignalProtocolStore{NewInMemorySignalProtocolStore()}
|
||||||
|
|
||||||
initializeSessions(t, aliceStore, bobStore.InMemorySignalProtocolStore, bobAddress, aliceAddress)
|
initializeSessions(t, aliceStore, bobStore.InMemorySignalProtocolStore, bobAddress)
|
||||||
|
|
||||||
alicePlaintext := []byte{8, 6, 7, 5, 3, 0, 9}
|
alicePlaintext := []byte{8, 6, 7, 5, 3, 0, 9}
|
||||||
|
|
||||||
aliceCiphertext, err := libsignalgo.Encrypt(ctx, alicePlaintext, bobAddress, aliceAddress, aliceStore, aliceStore)
|
aliceCiphertext, err := libsignalgo.Encrypt(ctx, alicePlaintext, bobAddress, aliceStore, aliceStore)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
aliceCiphertextMessageType, err := aliceCiphertext.MessageType()
|
aliceCiphertextMessageType, err := aliceCiphertext.MessageType()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
@ -198,7 +198,7 @@ func TestSessionCipherWithBadStore(t *testing.T) {
|
||||||
bobCiphertext, err := libsignalgo.DeserializePreKeyMessage(aliceCiphertextSerialized)
|
bobCiphertext, err := libsignalgo.DeserializePreKeyMessage(aliceCiphertextSerialized)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
t.Skip("This test is broken") // TODO fix
|
t.Skip("This test is broken") // TODO fix
|
||||||
_, err = libsignalgo.DecryptPreKey(ctx, bobCiphertext, aliceAddress, bobAddress, bobStore, bobStore, bobStore, bobStore, bobStore)
|
_, err = libsignalgo.DecryptPreKey(ctx, bobCiphertext, aliceAddress, bobStore, bobStore, bobStore, bobStore, bobStore)
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
assert.Equal(t, "Test error", err.Error())
|
assert.Equal(t, "Test error", err.Error())
|
||||||
}
|
}
|
||||||
|
|
@ -216,7 +216,7 @@ func TestSealedSenderEncrypt_Repeated(t *testing.T) {
|
||||||
aliceStore := NewInMemorySignalProtocolStore()
|
aliceStore := NewInMemorySignalProtocolStore()
|
||||||
bobStore := NewInMemorySignalProtocolStore()
|
bobStore := NewInMemorySignalProtocolStore()
|
||||||
|
|
||||||
initializeSessions(t, aliceStore, bobStore, bobAddress, aliceAddress)
|
initializeSessions(t, aliceStore, bobStore, bobAddress)
|
||||||
|
|
||||||
trustRoot, err := libsignalgo.GenerateIdentityKeyPair()
|
trustRoot, err := libsignalgo.GenerateIdentityKeyPair()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
@ -241,7 +241,7 @@ func TestSealedSenderEncrypt_Repeated(t *testing.T) {
|
||||||
}()
|
}()
|
||||||
for i := 0; i < 100; i++ {
|
for i := 0; i < 100; i++ {
|
||||||
message := []byte(fmt.Sprintf("%04d vision", i))
|
message := []byte(fmt.Sprintf("%04d vision", i))
|
||||||
ciphertext, err := libsignalgo.SealedSenderEncryptPlaintext(ctx, message, libsignalgo.UnidentifiedSenderMessageContentHintDefault, bobAddress, aliceAddress, senderCert, aliceStore, aliceStore, nil)
|
ciphertext, err := libsignalgo.SealedSenderEncryptPlaintext(ctx, message, libsignalgo.UnidentifiedSenderMessageContentHintDefault, bobAddress, senderCert, aliceStore, aliceStore, nil)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.NotNil(t, ciphertext)
|
assert.NotNil(t, ciphertext)
|
||||||
}
|
}
|
||||||
|
|
@ -252,18 +252,15 @@ func TestArchiveSession(t *testing.T) {
|
||||||
ctx := context.TODO()
|
ctx := context.TODO()
|
||||||
setupLogging()
|
setupLogging()
|
||||||
|
|
||||||
aliceACI := uuid.New()
|
|
||||||
bobACI := uuid.New()
|
bobACI := uuid.New()
|
||||||
|
|
||||||
aliceAddress, err := libsignalgo.NewACIServiceID(aliceACI).Address(1)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
bobAddress, err := libsignalgo.NewACIServiceID(bobACI).Address(1)
|
bobAddress, err := libsignalgo.NewACIServiceID(bobACI).Address(1)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
aliceStore := NewInMemorySignalProtocolStore()
|
aliceStore := NewInMemorySignalProtocolStore()
|
||||||
bobStore := NewInMemorySignalProtocolStore()
|
bobStore := NewInMemorySignalProtocolStore()
|
||||||
|
|
||||||
initializeSessions(t, aliceStore, bobStore, bobAddress, aliceAddress)
|
initializeSessions(t, aliceStore, bobStore, bobAddress)
|
||||||
|
|
||||||
session, err := aliceStore.LoadSession(ctx, bobAddress)
|
session, err := aliceStore.LoadSession(ctx, bobAddress)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
@ -318,7 +315,7 @@ func TestSealedSenderGroupCipher(t *testing.T) {
|
||||||
|
|
||||||
bobStore := NewInMemorySignalProtocolStore()
|
bobStore := NewInMemorySignalProtocolStore()
|
||||||
|
|
||||||
initializeSessions(t, aliceStore, bobStore, bobAddress, aliceAddress)
|
initializeSessions(t, aliceStore, bobStore, bobAddress)
|
||||||
|
|
||||||
trustRoot, err := libsignalgo.GenerateIdentityKeyPair()
|
trustRoot, err := libsignalgo.GenerateIdentityKeyPair()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
|
||||||
|
|
@ -67,8 +67,8 @@ func signal_destroy_session_store_callback(storeCtx unsafe.Pointer) {
|
||||||
func (ctx *CallbackContext) wrapSessionStore(store SessionStore) C.SignalConstPointerFfiSessionStoreStruct {
|
func (ctx *CallbackContext) wrapSessionStore(store SessionStore) C.SignalConstPointerFfiSessionStoreStruct {
|
||||||
return C.SignalConstPointerFfiSessionStoreStruct{&C.SignalSessionStore{
|
return C.SignalConstPointerFfiSessionStoreStruct{&C.SignalSessionStore{
|
||||||
ctx: wrapStore(ctx, store),
|
ctx: wrapStore(ctx, store),
|
||||||
load_session: C.SignalFfiSessionStoreLoadSession(C.signal_load_session_callback),
|
load_session: C.SignalFfiBridgeSessionStoreLoadSession(C.signal_load_session_callback),
|
||||||
store_session: C.SignalFfiSessionStoreStoreSession(C.signal_store_session_callback),
|
store_session: C.SignalFfiBridgeSessionStoreStoreSession(C.signal_store_session_callback),
|
||||||
destroy: C.SignalFfiSessionStoreDestroy(C.signal_destroy_session_store_callback),
|
destroy: C.SignalFfiBridgeSessionStoreDestroy(C.signal_destroy_session_store_callback),
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -54,8 +54,6 @@ func (FFILogger) Log(level libsignalgo.LogLevel, file string, line uint, message
|
||||||
|
|
||||||
func (FFILogger) Flush() {}
|
func (FFILogger) Flush() {}
|
||||||
|
|
||||||
func (FFILogger) Destroy() {}
|
|
||||||
|
|
||||||
var loggingSetup = false
|
var loggingSetup = false
|
||||||
|
|
||||||
func setupLogging() {
|
func setupLogging() {
|
||||||
|
|
|
||||||
|
|
@ -67,8 +67,8 @@ func signal_destroy_signed_pre_key_store_callback(storeCtx unsafe.Pointer) {
|
||||||
func (ctx *CallbackContext) wrapSignedPreKeyStore(store SignedPreKeyStore) C.SignalConstPointerFfiSignedPreKeyStoreStruct {
|
func (ctx *CallbackContext) wrapSignedPreKeyStore(store SignedPreKeyStore) C.SignalConstPointerFfiSignedPreKeyStoreStruct {
|
||||||
return C.SignalConstPointerFfiSignedPreKeyStoreStruct{&C.SignalSignedPreKeyStore{
|
return C.SignalConstPointerFfiSignedPreKeyStoreStruct{&C.SignalSignedPreKeyStore{
|
||||||
ctx: wrapStore(ctx, store),
|
ctx: wrapStore(ctx, store),
|
||||||
load_signed_pre_key: C.SignalFfiSignedPreKeyStoreLoadSignedPreKey(C.signal_load_signed_pre_key_callback),
|
load_signed_pre_key: C.SignalFfiBridgeSignedPreKeyStoreLoadSignedPreKey(C.signal_load_signed_pre_key_callback),
|
||||||
store_signed_pre_key: C.SignalFfiSignedPreKeyStoreStoreSignedPreKey(C.signal_store_signed_pre_key_callback),
|
store_signed_pre_key: C.SignalFfiBridgeSignedPreKeyStoreStoreSignedPreKey(C.signal_store_signed_pre_key_callback),
|
||||||
destroy: C.SignalFfiSignedPreKeyStoreDestroy(C.signal_destroy_signed_pre_key_store_callback),
|
destroy: C.SignalFfiBridgeSignedPreKeyStoreDestroy(C.signal_destroy_signed_pre_key_store_callback),
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,4 +2,4 @@
|
||||||
|
|
||||||
package libsignalgo
|
package libsignalgo
|
||||||
|
|
||||||
const Version = "v0.93.2"
|
const Version = "v0.89.1"
|
||||||
|
|
|
||||||
|
|
@ -110,9 +110,6 @@ func (mc *MessageConverter) ToSignal(
|
||||||
return nil, fmt.Errorf("failed to convert sticker: %w", err)
|
return nil, fmt.Errorf("failed to convert sticker: %w", err)
|
||||||
}
|
}
|
||||||
att.Flags = proto.Uint32(uint32(signalpb.AttachmentPointer_BORDERLESS))
|
att.Flags = proto.Uint32(uint32(signalpb.AttachmentPointer_BORDERLESS))
|
||||||
|
|
||||||
dm.Sticker = ParseStickerMeta(content.Info.BridgedSticker)
|
|
||||||
if dm.Sticker == nil {
|
|
||||||
var emoji *string
|
var emoji *string
|
||||||
// TODO check for single grapheme cluster?
|
// TODO check for single grapheme cluster?
|
||||||
if len([]rune(content.Body)) == 1 {
|
if len([]rune(content.Body)) == 1 {
|
||||||
|
|
@ -124,10 +121,10 @@ func (mc *MessageConverter) ToSignal(
|
||||||
PackId: make([]byte, 16),
|
PackId: make([]byte, 16),
|
||||||
PackKey: make([]byte, 32),
|
PackKey: make([]byte, 32),
|
||||||
StickerId: proto.Uint32(0),
|
StickerId: proto.Uint32(0),
|
||||||
|
|
||||||
|
Data: att,
|
||||||
Emoji: emoji,
|
Emoji: emoji,
|
||||||
}
|
}
|
||||||
}
|
|
||||||
dm.Sticker.Data = att
|
|
||||||
case event.MsgLocation:
|
case event.MsgLocation:
|
||||||
lat, lon, err := parseGeoURI(content.GeoURI)
|
lat, lon, err := parseGeoURI(content.GeoURI)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -468,16 +468,20 @@ func (mc *MessageConverter) convertStickerToMatrix(ctx context.Context, sticker
|
||||||
converted.Content.Info.Height = 200
|
converted.Content.Info.Height = 200
|
||||||
}
|
}
|
||||||
converted.Content.Body = sticker.GetEmoji()
|
converted.Content.Body = sticker.GetEmoji()
|
||||||
if len(sticker.GetPackId()) == PackIDLength && len(sticker.GetPackKey()) == PackKeyLength && !bytes.Equal(sticker.GetPackId(), zeroPackID) {
|
|
||||||
converted.Content.Info.BridgedSticker = &event.BridgedSticker{
|
|
||||||
Network: StickerSourceID,
|
|
||||||
ID: strconv.FormatUint(uint64(sticker.GetStickerId()), 10),
|
|
||||||
Emoji: sticker.GetEmoji(),
|
|
||||||
PackURL: fmt.Sprintf(PackURLFormat, sticker.GetPackId(), sticker.GetPackKey()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
converted.Type = event.EventSticker
|
converted.Type = event.EventSticker
|
||||||
converted.Content.MsgType = ""
|
converted.Content.MsgType = ""
|
||||||
|
if converted.Extra == nil {
|
||||||
|
converted.Extra = map[string]any{}
|
||||||
|
}
|
||||||
|
// TODO fetch full pack metadata like the old bridge did?
|
||||||
|
converted.Extra["fi.mau.signal.sticker"] = map[string]any{
|
||||||
|
"id": sticker.GetStickerId(),
|
||||||
|
"emoji": sticker.GetEmoji(),
|
||||||
|
"pack": map[string]any{
|
||||||
|
"id": sticker.GetPackId(),
|
||||||
|
"key": sticker.GetPackKey(),
|
||||||
|
},
|
||||||
|
}
|
||||||
return converted
|
return converted
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,199 +0,0 @@
|
||||||
// mautrix-signal - A Matrix-Signal puppeting bridge.
|
|
||||||
// Copyright (C) 2026 Tulir Asokan
|
|
||||||
//
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU Affero General Public License as published by
|
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU Affero General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Affero General Public License
|
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
package msgconv
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"context"
|
|
||||||
"encoding/hex"
|
|
||||||
"fmt"
|
|
||||||
"net/url"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"go.mau.fi/util/emojishortcodes"
|
|
||||||
"google.golang.org/protobuf/proto"
|
|
||||||
"maunium.net/go/mautrix"
|
|
||||||
"maunium.net/go/mautrix/bridgev2"
|
|
||||||
"maunium.net/go/mautrix/bridgev2/database"
|
|
||||||
"maunium.net/go/mautrix/event"
|
|
||||||
"maunium.net/go/mautrix/id"
|
|
||||||
|
|
||||||
"go.mau.fi/mautrix-signal/pkg/signalid"
|
|
||||||
"go.mau.fi/mautrix-signal/pkg/signalmeow"
|
|
||||||
signalpb "go.mau.fi/mautrix-signal/pkg/signalmeow/protobuf"
|
|
||||||
)
|
|
||||||
|
|
||||||
const StickerSourceID = "signal"
|
|
||||||
const PackURLFormat = "https://signal.art/addstickers/#pack_id=%x&pack_key=%x"
|
|
||||||
|
|
||||||
const PackIDLength = 16
|
|
||||||
const PackKeyLength = 32
|
|
||||||
const PackURLLength = len(PackURLFormat) - len("%x")*2 + PackIDLength*2 + PackKeyLength*2
|
|
||||||
|
|
||||||
var zeroPackID = make([]byte, PackIDLength)
|
|
||||||
|
|
||||||
func ParseStickerMeta(info *event.BridgedSticker) *signalpb.DataMessage_Sticker {
|
|
||||||
if info == nil || info.Network != StickerSourceID || len(info.PackURL) != PackURLLength {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
stickerID, err := strconv.ParseUint(info.ID, 10, 32)
|
|
||||||
if err != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
packID, packKey, err := parsePackURL(info.PackURL)
|
|
||||||
if err != nil || len(packID) != PackIDLength || len(packKey) != PackKeyLength || bytes.Equal(packID, zeroPackID) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return &signalpb.DataMessage_Sticker{
|
|
||||||
PackId: packID,
|
|
||||||
PackKey: packKey,
|
|
||||||
StickerId: proto.Uint32(uint32(stickerID)),
|
|
||||||
Emoji: &info.Emoji,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func parsePackURL(rawURL string) (packID, packKey []byte, err error) {
|
|
||||||
parsed, err := url.Parse(rawURL)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, fmt.Errorf("invalid URL: %w", err)
|
|
||||||
} else if parsed.Host != "signal.art" || !strings.HasPrefix(parsed.Path, "/addstickers") {
|
|
||||||
return nil, nil, fmt.Errorf("invalid host or path in URL")
|
|
||||||
}
|
|
||||||
q, err := url.ParseQuery(parsed.Fragment)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, fmt.Errorf("invalid URL fragment: %w", err)
|
|
||||||
}
|
|
||||||
packID, err = hex.DecodeString(q.Get("pack_id"))
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, fmt.Errorf("invalid pack ID in URL: %w", err)
|
|
||||||
}
|
|
||||||
packKey, err = hex.DecodeString(q.Get("pack_key"))
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, fmt.Errorf("invalid pack key in URL: %w", err)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (mc *MessageConverter) DownloadImagePack(ctx context.Context, url string) (*bridgev2.ImportedImagePack, error) {
|
|
||||||
packID, packKey, err := parsePackURL(url)
|
|
||||||
if err != nil {
|
|
||||||
return nil, bridgev2.WrapRespErr(err, mautrix.MNotFound)
|
|
||||||
}
|
|
||||||
manifest, err := signalmeow.DownloadStickerPackManifest(ctx, packID, packKey)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to download sticker pack manifest: %w", err)
|
|
||||||
}
|
|
||||||
topLevelExtra := map[string]any{
|
|
||||||
"fi.mau.signal.stickerpack": map[string]any{
|
|
||||||
"pack_id": hex.EncodeToString(packID),
|
|
||||||
"pack_key": hex.EncodeToString(packKey),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
content := &event.ImagePackEventContent{
|
|
||||||
Images: make(map[string]*event.ImagePackImage, len(manifest.Stickers)),
|
|
||||||
Metadata: event.ImagePackMetadata{
|
|
||||||
DisplayName: manifest.GetTitle(),
|
|
||||||
AvatarURL: "",
|
|
||||||
Usage: []event.ImagePackUsage{event.ImagePackUsageSticker},
|
|
||||||
Attribution: manifest.GetAuthor(),
|
|
||||||
BridgedPack: &event.BridgedStickerPack{
|
|
||||||
Network: StickerSourceID,
|
|
||||||
URL: fmt.Sprintf(PackURLFormat, packID, packKey),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
imagesByID := make(map[uint32]id.ContentURIString, len(manifest.Stickers))
|
|
||||||
uploadImage := func(sticker *signalpb.Pack_Sticker) (id.ContentURIString, error) {
|
|
||||||
stickerID := sticker.GetId()
|
|
||||||
existing, ok := imagesByID[stickerID]
|
|
||||||
if ok {
|
|
||||||
return existing, nil
|
|
||||||
}
|
|
||||||
var mxc id.ContentURIString
|
|
||||||
if mc.DirectMedia {
|
|
||||||
mediaID, err := signalid.DirectMediaSticker{
|
|
||||||
PackID: packID,
|
|
||||||
PackKey: packKey,
|
|
||||||
StickerID: stickerID,
|
|
||||||
}.AsMediaID()
|
|
||||||
if err != nil {
|
|
||||||
return "", fmt.Errorf("failed to create media ID for sticker %d: %w", stickerID, err)
|
|
||||||
}
|
|
||||||
mxc, err = mc.Bridge.Matrix.GenerateContentURI(ctx, mediaID)
|
|
||||||
if err != nil {
|
|
||||||
return "", fmt.Errorf("failed to generate content URI for sticker %d: %w", stickerID, err)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
dbKey := database.Key(fmt.Sprintf("stickercache:%x:%d", packID, stickerID))
|
|
||||||
if cached := mc.Bridge.DB.KV.Get(ctx, dbKey); cached != "" {
|
|
||||||
mxc = id.ContentURIString(cached)
|
|
||||||
imagesByID[stickerID] = mxc
|
|
||||||
return mxc, nil
|
|
||||||
}
|
|
||||||
data, err := signalmeow.DownloadStickerPackItem(ctx, packID, packKey, stickerID)
|
|
||||||
if err != nil {
|
|
||||||
return "", fmt.Errorf("failed to download sticker %d: %w", stickerID, err)
|
|
||||||
}
|
|
||||||
mxc, _, err = mc.Bridge.Bot.UploadMedia(ctx, "", data, "", sticker.GetContentType())
|
|
||||||
if err != nil {
|
|
||||||
return "", fmt.Errorf("failed to upload sticker %d: %w", stickerID, err)
|
|
||||||
}
|
|
||||||
mc.Bridge.DB.KV.Set(ctx, dbKey, string(mxc))
|
|
||||||
}
|
|
||||||
imagesByID[stickerID] = mxc
|
|
||||||
return mxc, nil
|
|
||||||
}
|
|
||||||
for _, sticker := range manifest.Stickers {
|
|
||||||
mxc, err := uploadImage(sticker)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
shortcode := emojishortcodes.Get(sticker.GetEmoji())
|
|
||||||
realShortcode := shortcode
|
|
||||||
i := 2
|
|
||||||
for _, alreadyExists := content.Images[realShortcode]; alreadyExists; i++ {
|
|
||||||
realShortcode = fmt.Sprintf("%s_%d", shortcode, i)
|
|
||||||
}
|
|
||||||
content.Images[realShortcode] = &event.ImagePackImage{
|
|
||||||
URL: mxc,
|
|
||||||
Body: sticker.GetEmoji(),
|
|
||||||
Info: &event.FileInfo{
|
|
||||||
MimeType: sticker.GetContentType(),
|
|
||||||
Width: 200,
|
|
||||||
Height: 200,
|
|
||||||
BridgedSticker: &event.BridgedSticker{
|
|
||||||
Network: StickerSourceID,
|
|
||||||
ID: strconv.FormatUint(uint64(sticker.GetId()), 10),
|
|
||||||
Emoji: sticker.GetEmoji(),
|
|
||||||
PackURL: content.Metadata.BridgedPack.URL,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if manifest.Cover != nil {
|
|
||||||
content.Metadata.AvatarURL, err = uploadImage(manifest.Cover)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to upload sticker pack cover: %w", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return &bridgev2.ImportedImagePack{
|
|
||||||
Content: content,
|
|
||||||
Extra: topLevelExtra,
|
|
||||||
Shortcode: hex.EncodeToString(packID),
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
@ -34,7 +34,6 @@ const (
|
||||||
directMediaTypeGroupAvatar directMediaType = 1
|
directMediaTypeGroupAvatar directMediaType = 1
|
||||||
directMediaTypeProfileAvatar directMediaType = 2
|
directMediaTypeProfileAvatar directMediaType = 2
|
||||||
directMediaTypePlaintextDigestAttachment directMediaType = 3
|
directMediaTypePlaintextDigestAttachment directMediaType = 3
|
||||||
directMediaTypeSticker directMediaType = 4
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type DirectMediaInfo interface {
|
type DirectMediaInfo interface {
|
||||||
|
|
@ -45,7 +44,6 @@ var (
|
||||||
_ DirectMediaInfo = (*DirectMediaAttachment)(nil)
|
_ DirectMediaInfo = (*DirectMediaAttachment)(nil)
|
||||||
_ DirectMediaInfo = (*DirectMediaGroupAvatar)(nil)
|
_ DirectMediaInfo = (*DirectMediaGroupAvatar)(nil)
|
||||||
_ DirectMediaInfo = (*DirectMediaProfileAvatar)(nil)
|
_ DirectMediaInfo = (*DirectMediaProfileAvatar)(nil)
|
||||||
_ DirectMediaInfo = (*DirectMediaSticker)(nil)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type DirectMediaAttachment struct {
|
type DirectMediaAttachment struct {
|
||||||
|
|
@ -129,30 +127,6 @@ func (m DirectMediaProfileAvatar) AsMediaID() (mediaID networkid.MediaID, err er
|
||||||
return networkid.MediaID(buf.Bytes()), nil
|
return networkid.MediaID(buf.Bytes()), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type DirectMediaSticker struct {
|
|
||||||
PackID []byte
|
|
||||||
PackKey []byte
|
|
||||||
StickerID uint32
|
|
||||||
}
|
|
||||||
|
|
||||||
const packIDLen = 16
|
|
||||||
const packKeyLen = 32
|
|
||||||
const directMediaStickerLen = 1 + packIDLen + packKeyLen + 4
|
|
||||||
|
|
||||||
func (m DirectMediaSticker) AsMediaID() (mediaID networkid.MediaID, err error) {
|
|
||||||
if len(m.PackID) != packIDLen {
|
|
||||||
return nil, fmt.Errorf("invalid pack ID length: %d", len(m.PackID))
|
|
||||||
} else if len(m.PackKey) != packKeyLen {
|
|
||||||
return nil, fmt.Errorf("invalid pack key length: %d", len(m.PackKey))
|
|
||||||
}
|
|
||||||
mediaID = make(networkid.MediaID, directMediaStickerLen)
|
|
||||||
mediaID[0] = byte(directMediaTypeSticker)
|
|
||||||
copy(mediaID[1:], m.PackID)
|
|
||||||
copy(mediaID[1+packIDLen:], m.PackKey)
|
|
||||||
binary.BigEndian.PutUint32(mediaID[1+packIDLen+packKeyLen:], m.StickerID)
|
|
||||||
return mediaID, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func ParseDirectMediaInfo(mediaID networkid.MediaID) (_ DirectMediaInfo, err error) {
|
func ParseDirectMediaInfo(mediaID networkid.MediaID) (_ DirectMediaInfo, err error) {
|
||||||
mediaIDLen := len(mediaID)
|
mediaIDLen := len(mediaID)
|
||||||
if mediaIDLen == 0 {
|
if mediaIDLen == 0 {
|
||||||
|
|
@ -226,15 +200,6 @@ func ParseDirectMediaInfo(mediaID networkid.MediaID) (_ DirectMediaInfo, err err
|
||||||
info.ProfileAvatarPath = string(profileAvatarPath)
|
info.ProfileAvatarPath = string(profileAvatarPath)
|
||||||
}
|
}
|
||||||
return &info, nil
|
return &info, nil
|
||||||
case directMediaTypeSticker:
|
|
||||||
var info DirectMediaSticker
|
|
||||||
if len(mediaID) != directMediaStickerLen {
|
|
||||||
return info, fmt.Errorf("invalid media ID length for sticker: %d", len(mediaID))
|
|
||||||
}
|
|
||||||
info.PackID = mediaID[1 : 1+packIDLen]
|
|
||||||
info.PackKey = mediaID[1+packIDLen : 1+packIDLen+packKeyLen]
|
|
||||||
info.StickerID = binary.BigEndian.Uint32(mediaID[1+packIDLen+packKeyLen:])
|
|
||||||
return &info, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, fmt.Errorf("invalid direct media type %d", mediaType)
|
return nil, fmt.Errorf("invalid direct media type %d", mediaType)
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,6 @@ import (
|
||||||
|
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
"go.mau.fi/util/fallocate"
|
"go.mau.fi/util/fallocate"
|
||||||
"go.mau.fi/util/pkcs7"
|
|
||||||
"go.mau.fi/util/random"
|
"go.mau.fi/util/random"
|
||||||
"google.golang.org/protobuf/proto"
|
"google.golang.org/protobuf/proto"
|
||||||
|
|
||||||
|
|
@ -94,20 +93,15 @@ func DownloadAttachment(
|
||||||
|
|
||||||
var body []byte
|
var body []byte
|
||||||
var downloadedSize int64
|
var downloadedSize int64
|
||||||
if resp.StatusCode > 400 {
|
if into == nil || resp.StatusCode > 400 {
|
||||||
body, err = io.ReadAll(io.LimitReader(resp.Body, 4096))
|
body, err = io.ReadAll(resp.Body)
|
||||||
} else if into == nil {
|
} else {
|
||||||
if resp.ContentLength > 0 {
|
if resp.ContentLength > 0 {
|
||||||
body = make([]byte, resp.ContentLength)
|
|
||||||
_, err = io.ReadFull(resp.Body, body)
|
|
||||||
} else {
|
|
||||||
body, err = io.ReadAll(http.MaxBytesReader(nil, resp.Body, max(int64(size), 32*1024)*2))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
err = fallocate.Fallocate(into, int(resp.ContentLength))
|
err = fallocate.Fallocate(into, int(resp.ContentLength))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to pre-allocate file for attachment: %w", err)
|
return nil, fmt.Errorf("failed to pre-allocate file for attachment: %w", err)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
downloadedSize, err = io.Copy(into, resp.Body)
|
downloadedSize, err = io.Copy(into, resp.Body)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -137,15 +131,6 @@ func DownloadAttachment(
|
||||||
const MACLength = 32
|
const MACLength = 32
|
||||||
const IVLength = 16
|
const IVLength = 16
|
||||||
|
|
||||||
func macAndAESDecrypt(body, key []byte) ([]byte, error) {
|
|
||||||
l := len(body) - MACLength
|
|
||||||
if !verifyMAC(key[MACLength:], body[:l], body[l:]) {
|
|
||||||
return nil, ErrInvalidMACForAttachment
|
|
||||||
}
|
|
||||||
|
|
||||||
return aesDecrypt(key[:MACLength], body[:l])
|
|
||||||
}
|
|
||||||
|
|
||||||
func decryptAttachment(body, key, digest []byte, plaintextDigest bool, size uint32) ([]byte, error) {
|
func decryptAttachment(body, key, digest []byte, plaintextDigest bool, size uint32) ([]byte, error) {
|
||||||
if !plaintextDigest {
|
if !plaintextDigest {
|
||||||
hash := sha256.Sum256(body)
|
hash := sha256.Sum256(body)
|
||||||
|
|
@ -153,7 +138,12 @@ func decryptAttachment(body, key, digest []byte, plaintextDigest bool, size uint
|
||||||
return nil, ErrInvalidDigestForAttachment
|
return nil, ErrInvalidDigestForAttachment
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
decrypted, err := macAndAESDecrypt(body, key)
|
l := len(body) - MACLength
|
||||||
|
if !verifyMAC(key[MACLength:], body[:l], body[l:]) {
|
||||||
|
return nil, ErrInvalidMACForAttachment
|
||||||
|
}
|
||||||
|
|
||||||
|
decrypted, err := aesDecrypt(key[:MACLength], body[:l])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -245,14 +235,6 @@ func extend(data []byte, paddedLen int) []byte {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func macAndAESEncrypt(keys, plaintext []byte) ([]byte, error) {
|
|
||||||
encrypted, err := aesEncrypt(keys[:32], plaintext)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return appendMAC(keys[32:], encrypted), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (cli *Client) UploadAttachment(ctx context.Context, body []byte) (*signalpb.AttachmentPointer, error) {
|
func (cli *Client) UploadAttachment(ctx context.Context, body []byte) (*signalpb.AttachmentPointer, error) {
|
||||||
log := zerolog.Ctx(ctx).With().Str("func", "upload attachment").Logger()
|
log := zerolog.Ctx(ctx).With().Str("func", "upload attachment").Logger()
|
||||||
keys := random.Bytes(64) // combined AES and MAC keys
|
keys := random.Bytes(64) // combined AES and MAC keys
|
||||||
|
|
@ -268,10 +250,11 @@ func (cli *Client) UploadAttachment(ctx context.Context, body []byte) (*signalpb
|
||||||
}
|
}
|
||||||
body = extend(body, paddedLen)
|
body = extend(body, paddedLen)
|
||||||
|
|
||||||
encryptedWithMAC, err := macAndAESEncrypt(keys, body)
|
encrypted, err := aesEncrypt(keys[:32], body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
encryptedWithMAC := appendMAC(keys[32:], encrypted)
|
||||||
|
|
||||||
// Get upload attributes from Signal server
|
// Get upload attributes from Signal server
|
||||||
attributesPath := "/v4/attachments/form/upload"
|
attributesPath := "/v4/attachments/form/upload"
|
||||||
|
|
@ -381,17 +364,12 @@ func (cli *Client) uploadAttachmentTUS(
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cli *Client) UploadGroupAvatar(ctx context.Context, avatarBytes []byte, gid types.GroupIdentifier, groupMasterKey types.SerializedGroupMasterKey) (string, error) {
|
func (cli *Client) UploadGroupAvatar(ctx context.Context, avatarBytes []byte, gid types.GroupIdentifier) (string, error) {
|
||||||
log := zerolog.Ctx(ctx)
|
log := zerolog.Ctx(ctx)
|
||||||
if groupMasterKey == "" {
|
groupMasterKey, err := cli.Store.GroupStore.MasterKeyFromGroupIdentifier(ctx, gid)
|
||||||
var err error
|
|
||||||
groupMasterKey, err = cli.Store.GroupStore.MasterKeyFromGroupIdentifier(ctx, gid)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Err(err).Msg("Could not get master key from group id")
|
log.Err(err).Msg("Could not get master key from group id")
|
||||||
return "", err
|
return "", err
|
||||||
} else if groupMasterKey == "" {
|
|
||||||
return "", fmt.Errorf("no master key found for group %s", gid)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
groupAuth, err := cli.GetAuthorizationForToday(ctx, masterKeyToBytes(groupMasterKey))
|
groupAuth, err := cli.GetAuthorizationForToday(ctx, masterKeyToBytes(groupMasterKey))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -479,10 +457,13 @@ func aesDecrypt(key, ciphertext []byte) ([]byte, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
iv := ciphertext[:IVLength]
|
iv := ciphertext[:IVLength]
|
||||||
ciphertext = ciphertext[IVLength:]
|
|
||||||
mode := cipher.NewCBCDecrypter(block, iv)
|
mode := cipher.NewCBCDecrypter(block, iv)
|
||||||
mode.CryptBlocks(ciphertext, ciphertext)
|
mode.CryptBlocks(ciphertext, ciphertext)
|
||||||
return pkcs7.Unpad(ciphertext)
|
pad := ciphertext[len(ciphertext)-1]
|
||||||
|
if pad > aes.BlockSize {
|
||||||
|
return nil, fmt.Errorf("pad value (%d) larger than AES blocksize (%d)", pad, aes.BlockSize)
|
||||||
|
}
|
||||||
|
return ciphertext[aes.BlockSize : len(ciphertext)-int(pad)], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func aesDecryptFile(key []byte, file *os.File, downloadedSize int64) (int64, error) {
|
func aesDecryptFile(key []byte, file *os.File, downloadedSize int64) (int64, error) {
|
||||||
|
|
@ -542,11 +523,14 @@ func aesEncrypt(key, plaintext []byte) ([]byte, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
plaintext = pkcs7.Pad(plaintext, aes.BlockSize)
|
pad := aes.BlockSize - len(plaintext)%aes.BlockSize
|
||||||
|
plaintext = append(plaintext, bytes.Repeat([]byte{byte(pad)}, pad)...)
|
||||||
|
|
||||||
|
ciphertext := make([]byte, len(plaintext))
|
||||||
iv := random.Bytes(16)
|
iv := random.Bytes(16)
|
||||||
|
|
||||||
mode := cipher.NewCBCEncrypter(block, iv)
|
mode := cipher.NewCBCEncrypter(block, iv)
|
||||||
mode.CryptBlocks(plaintext, plaintext)
|
mode.CryptBlocks(ciphertext, plaintext)
|
||||||
|
|
||||||
return append(iv, plaintext...), nil
|
return append(iv, ciphertext...), nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -282,11 +282,7 @@ func (cli *Client) WaitForTransfer(ctx context.Context) (*TransferArchiveMetadat
|
||||||
}
|
}
|
||||||
reqDuration := time.Since(reqStart)
|
reqDuration := time.Since(reqStart)
|
||||||
if reqDuration < reqTimeout-10*time.Second {
|
if reqDuration < reqTimeout-10*time.Second {
|
||||||
select {
|
time.Sleep(15 * time.Second)
|
||||||
case <-time.After(15 * time.Second):
|
|
||||||
case <-ctx.Done():
|
|
||||||
return nil, ctx.Err()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -619,7 +619,7 @@ func (cli *Client) fetchGroupByID(ctx context.Context, gid types.GroupIdentifier
|
||||||
return nil, fmt.Errorf("failed to get group master key: %w", err)
|
return nil, fmt.Errorf("failed to get group master key: %w", err)
|
||||||
}
|
}
|
||||||
if groupMasterKey == "" {
|
if groupMasterKey == "" {
|
||||||
return nil, fmt.Errorf("%w for %s", ErrGroupMasterKeyNotFound, gid)
|
return nil, fmt.Errorf("No group master key found for group identifier %s", gid)
|
||||||
}
|
}
|
||||||
return cli.fetchGroupWithMasterKey(ctx, groupMasterKey)
|
return cli.fetchGroupWithMasterKey(ctx, groupMasterKey)
|
||||||
}
|
}
|
||||||
|
|
@ -1513,15 +1513,11 @@ func (cli *Client) patchGroup(ctx context.Context, groupChange *signalpb.GroupCh
|
||||||
return &changeResp, nil
|
return &changeResp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var ErrGroupMasterKeyNotFound = errors.New("group master key not found in store")
|
|
||||||
|
|
||||||
func (cli *Client) UpdateGroup(ctx context.Context, groupChange *GroupChange, gid types.GroupIdentifier) (uint32, error) {
|
func (cli *Client) UpdateGroup(ctx context.Context, groupChange *GroupChange, gid types.GroupIdentifier) (uint32, error) {
|
||||||
log := zerolog.Ctx(ctx).With().Str("action", "UpdateGroup").Logger()
|
log := zerolog.Ctx(ctx).With().Str("action", "UpdateGroup").Logger()
|
||||||
groupMasterKey, err := cli.Store.GroupStore.MasterKeyFromGroupIdentifier(ctx, gid)
|
groupMasterKey, err := cli.Store.GroupStore.MasterKeyFromGroupIdentifier(ctx, gid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, fmt.Errorf("failed to get master key for group: %w", err)
|
return 0, fmt.Errorf("failed to get master key for group: %w", err)
|
||||||
} else if groupMasterKey == "" {
|
|
||||||
return 0, ErrGroupMasterKeyNotFound
|
|
||||||
}
|
}
|
||||||
groupChange.GroupMasterKey = groupMasterKey
|
groupChange.GroupMasterKey = groupMasterKey
|
||||||
masterKeyBytes := masterKeyToBytes(groupMasterKey)
|
masterKeyBytes := masterKeyToBytes(groupMasterKey)
|
||||||
|
|
@ -1666,7 +1662,7 @@ func PrepareGroupCreation(decryptedGroup *Group) (libsignalgo.GroupMasterKey, er
|
||||||
return masterKeyBytes, nil
|
return masterKeyBytes, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cli *Client) createGroupOnServer(ctx context.Context, decryptedGroup *Group) (*Group, error) {
|
func (cli *Client) createGroupOnServer(ctx context.Context, decryptedGroup *Group, avatarBytes []byte) (*Group, error) {
|
||||||
log := zerolog.Ctx(ctx).With().Str("action", "CreateGroupOnServer").Logger()
|
log := zerolog.Ctx(ctx).With().Str("action", "CreateGroupOnServer").Logger()
|
||||||
masterKeyBytes, err := PrepareGroupCreation(decryptedGroup)
|
masterKeyBytes, err := PrepareGroupCreation(decryptedGroup)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -1681,6 +1677,14 @@ func (cli *Client) createGroupOnServer(ctx context.Context, decryptedGroup *Grou
|
||||||
log.Err(err).Msg("DeriveGroupSecretParamsFromMasterKey error")
|
log.Err(err).Msg("DeriveGroupSecretParamsFromMasterKey error")
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if len(avatarBytes) > 0 {
|
||||||
|
avatarPath, err := cli.UploadGroupAvatar(ctx, avatarBytes, decryptedGroup.GroupIdentifier)
|
||||||
|
if err != nil {
|
||||||
|
log.Err(err).Msg("Failed to upload group avatar")
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
decryptedGroup.AvatarPath = avatarPath
|
||||||
|
}
|
||||||
encryptedGroup, err := cli.EncryptGroup(ctx, decryptedGroup, groupSecretParams)
|
encryptedGroup, err := cli.EncryptGroup(ctx, decryptedGroup, groupSecretParams)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Err(err).Msg("Failed to encrypt group")
|
log.Err(err).Msg("Failed to encrypt group")
|
||||||
|
|
@ -1731,9 +1735,9 @@ func GenerateInviteLinkPassword() types.SerializedInviteLinkPassword {
|
||||||
return InviteLinkPasswordFromBytes(random.Bytes(16))
|
return InviteLinkPasswordFromBytes(random.Bytes(16))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cli *Client) CreateGroup(ctx context.Context, decryptedGroup *Group) (*Group, error) {
|
func (cli *Client) CreateGroup(ctx context.Context, decryptedGroup *Group, avatarBytes []byte) (*Group, error) {
|
||||||
log := zerolog.Ctx(ctx).With().Str("action", "CreateGroup").Logger()
|
log := zerolog.Ctx(ctx).With().Str("action", "CreateGroup").Logger()
|
||||||
group, err := cli.createGroupOnServer(ctx, decryptedGroup)
|
group, err := cli.createGroupOnServer(ctx, decryptedGroup, avatarBytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Err(err).Msg("Error creating group on server")
|
log.Err(err).Msg("Error creating group on server")
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -1756,7 +1760,7 @@ func (cli *Client) GetGroupHistoryPage(ctx context.Context, gid types.GroupIdent
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if groupMasterKey == "" {
|
if groupMasterKey == "" {
|
||||||
return nil, ErrGroupMasterKeyNotFound
|
return nil, fmt.Errorf("No group master key found for group identifier %s", gid)
|
||||||
}
|
}
|
||||||
masterKeyBytes := masterKeyToBytes(groupMasterKey)
|
masterKeyBytes := masterKeyToBytes(groupMasterKey)
|
||||||
groupAuth, err := cli.GetAuthorizationForToday(ctx, masterKeyBytes)
|
groupAuth, err := cli.GetAuthorizationForToday(ctx, masterKeyBytes)
|
||||||
|
|
|
||||||
|
|
@ -413,10 +413,6 @@ func (cli *Client) FetchAndProcessPreKey(ctx context.Context, theirServiceID lib
|
||||||
if cli.Store.RecipientStore.IsUnregistered(ctx, theirServiceID) {
|
if cli.Store.RecipientStore.IsUnregistered(ctx, theirServiceID) {
|
||||||
return fmt.Errorf("%w (cached)", ErrUnregisteredUser)
|
return fmt.Errorf("%w (cached)", ErrUnregisteredUser)
|
||||||
}
|
}
|
||||||
localAddress, err := cli.Store.ACIServiceID().Address(uint(cli.Store.DeviceID))
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to get own address: %w", err)
|
|
||||||
}
|
|
||||||
// Fetch prekey
|
// Fetch prekey
|
||||||
deviceIDPath := "/*"
|
deviceIDPath := "/*"
|
||||||
if specificDeviceID >= 0 {
|
if specificDeviceID >= 0 {
|
||||||
|
|
@ -522,7 +518,6 @@ func (cli *Client) FetchAndProcessPreKey(ctx context.Context, theirServiceID lib
|
||||||
ctx,
|
ctx,
|
||||||
preKeyBundle,
|
preKeyBundle,
|
||||||
address,
|
address,
|
||||||
localAddress,
|
|
||||||
cli.Store.ACISessionStore,
|
cli.Store.ACISessionStore,
|
||||||
cli.Store.ACIIdentityStore,
|
cli.Store.ACIIdentityStore,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -69,8 +69,6 @@ func (l FFILogger) Log(level libsignalgo.LogLevel, file string, line uint, messa
|
||||||
|
|
||||||
func (FFILogger) Flush() {}
|
func (FFILogger) Flush() {}
|
||||||
|
|
||||||
func (FFILogger) Destroy() {}
|
|
||||||
|
|
||||||
// Ensure FFILogger implements the Logger interface
|
// Ensure FFILogger implements the Logger interface
|
||||||
var _ libsignalgo.Logger = FFILogger{}
|
var _ libsignalgo.Logger = FFILogger{}
|
||||||
|
|
||||||
|
|
|
||||||
2
pkg/signalmeow/protobuf/ContactDiscovery.pb.go
generated
2
pkg/signalmeow/protobuf/ContactDiscovery.pb.go
generated
|
|
@ -1,7 +1,7 @@
|
||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// protoc-gen-go v1.36.11
|
// protoc-gen-go v1.36.11
|
||||||
// protoc v7.34.1
|
// protoc v6.33.5
|
||||||
// source: ContactDiscovery.proto
|
// source: ContactDiscovery.proto
|
||||||
|
|
||||||
// Copyright 2021 Signal Messenger, LLC
|
// Copyright 2021 Signal Messenger, LLC
|
||||||
|
|
|
||||||
2
pkg/signalmeow/protobuf/DeviceName.pb.go
generated
2
pkg/signalmeow/protobuf/DeviceName.pb.go
generated
|
|
@ -1,7 +1,7 @@
|
||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// protoc-gen-go v1.36.11
|
// protoc-gen-go v1.36.11
|
||||||
// protoc v7.34.1
|
// protoc v6.33.5
|
||||||
// source: DeviceName.proto
|
// source: DeviceName.proto
|
||||||
|
|
||||||
// Copyright 2018 Signal Messenger, LLC
|
// Copyright 2018 Signal Messenger, LLC
|
||||||
|
|
|
||||||
273
pkg/signalmeow/protobuf/Groups.pb.go
generated
273
pkg/signalmeow/protobuf/Groups.pb.go
generated
|
|
@ -5,7 +5,7 @@
|
||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// protoc-gen-go v1.36.11
|
// protoc-gen-go v1.36.11
|
||||||
// protoc v7.34.1
|
// protoc v6.33.5
|
||||||
// source: Groups.proto
|
// source: Groups.proto
|
||||||
|
|
||||||
package signalpb
|
package signalpb
|
||||||
|
|
@ -498,7 +498,6 @@ type AccessControl struct {
|
||||||
Attributes AccessControl_AccessRequired `protobuf:"varint,1,opt,name=attributes,proto3,enum=signal.AccessControl_AccessRequired" json:"attributes,omitempty"`
|
Attributes AccessControl_AccessRequired `protobuf:"varint,1,opt,name=attributes,proto3,enum=signal.AccessControl_AccessRequired" json:"attributes,omitempty"`
|
||||||
Members AccessControl_AccessRequired `protobuf:"varint,2,opt,name=members,proto3,enum=signal.AccessControl_AccessRequired" json:"members,omitempty"`
|
Members AccessControl_AccessRequired `protobuf:"varint,2,opt,name=members,proto3,enum=signal.AccessControl_AccessRequired" json:"members,omitempty"`
|
||||||
AddFromInviteLink AccessControl_AccessRequired `protobuf:"varint,3,opt,name=addFromInviteLink,proto3,enum=signal.AccessControl_AccessRequired" json:"addFromInviteLink,omitempty"`
|
AddFromInviteLink AccessControl_AccessRequired `protobuf:"varint,3,opt,name=addFromInviteLink,proto3,enum=signal.AccessControl_AccessRequired" json:"addFromInviteLink,omitempty"`
|
||||||
MemberLabel AccessControl_AccessRequired `protobuf:"varint,4,opt,name=memberLabel,proto3,enum=signal.AccessControl_AccessRequired" json:"memberLabel,omitempty"`
|
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
}
|
}
|
||||||
|
|
@ -554,13 +553,6 @@ func (x *AccessControl) GetAddFromInviteLink() AccessControl_AccessRequired {
|
||||||
return AccessControl_UNKNOWN
|
return AccessControl_UNKNOWN
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *AccessControl) GetMemberLabel() AccessControl_AccessRequired {
|
|
||||||
if x != nil {
|
|
||||||
return x.MemberLabel
|
|
||||||
}
|
|
||||||
return AccessControl_UNKNOWN
|
|
||||||
}
|
|
||||||
|
|
||||||
type Group struct {
|
type Group struct {
|
||||||
state protoimpl.MessageState `protogen:"open.v1"`
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
PublicKey []byte `protobuf:"bytes,1,opt,name=publicKey,proto3" json:"publicKey,omitempty"`
|
PublicKey []byte `protobuf:"bytes,1,opt,name=publicKey,proto3" json:"publicKey,omitempty"`
|
||||||
|
|
@ -577,8 +569,7 @@ type Group struct {
|
||||||
MembersPendingAdminApproval []*MemberPendingAdminApproval `protobuf:"bytes,9,rep,name=membersPendingAdminApproval,proto3" json:"membersPendingAdminApproval,omitempty"`
|
MembersPendingAdminApproval []*MemberPendingAdminApproval `protobuf:"bytes,9,rep,name=membersPendingAdminApproval,proto3" json:"membersPendingAdminApproval,omitempty"`
|
||||||
InviteLinkPassword []byte `protobuf:"bytes,10,opt,name=inviteLinkPassword,proto3" json:"inviteLinkPassword,omitempty"`
|
InviteLinkPassword []byte `protobuf:"bytes,10,opt,name=inviteLinkPassword,proto3" json:"inviteLinkPassword,omitempty"`
|
||||||
AnnouncementsOnly bool `protobuf:"varint,12,opt,name=announcements_only,json=announcementsOnly,proto3" json:"announcements_only,omitempty"`
|
AnnouncementsOnly bool `protobuf:"varint,12,opt,name=announcements_only,json=announcementsOnly,proto3" json:"announcements_only,omitempty"`
|
||||||
MembersBanned []*MemberBanned `protobuf:"bytes,13,rep,name=members_banned,json=membersBanned,proto3" json:"members_banned,omitempty"`
|
MembersBanned []*MemberBanned `protobuf:"bytes,13,rep,name=members_banned,json=membersBanned,proto3" json:"members_banned,omitempty"` // next: 14
|
||||||
Terminated bool `protobuf:"varint,14,opt,name=terminated,proto3" json:"terminated,omitempty"` // next: 15
|
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
}
|
}
|
||||||
|
|
@ -704,13 +695,6 @@ func (x *Group) GetMembersBanned() []*MemberBanned {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Group) GetTerminated() bool {
|
|
||||||
if x != nil {
|
|
||||||
return x.Terminated
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
type GroupAttributeBlob struct {
|
type GroupAttributeBlob struct {
|
||||||
state protoimpl.MessageState `protogen:"open.v1"`
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
// Types that are valid to be assigned to Content:
|
// Types that are valid to be assigned to Content:
|
||||||
|
|
@ -1333,8 +1317,6 @@ type GroupChange_Actions struct {
|
||||||
DeleteMembersBanned []*GroupChange_Actions_DeleteMemberBannedAction `protobuf:"bytes,23,rep,name=delete_members_banned,json=deleteMembersBanned,proto3" json:"delete_members_banned,omitempty"` // change epoch = 4
|
DeleteMembersBanned []*GroupChange_Actions_DeleteMemberBannedAction `protobuf:"bytes,23,rep,name=delete_members_banned,json=deleteMembersBanned,proto3" json:"delete_members_banned,omitempty"` // change epoch = 4
|
||||||
PromoteMembersPendingPniAciProfileKey []*GroupChange_Actions_PromoteMemberPendingPniAciProfileKeyAction `protobuf:"bytes,24,rep,name=promote_members_pending_pni_aci_profile_key,json=promoteMembersPendingPniAciProfileKey,proto3" json:"promote_members_pending_pni_aci_profile_key,omitempty"` // change epoch = 5
|
PromoteMembersPendingPniAciProfileKey []*GroupChange_Actions_PromoteMemberPendingPniAciProfileKeyAction `protobuf:"bytes,24,rep,name=promote_members_pending_pni_aci_profile_key,json=promoteMembersPendingPniAciProfileKey,proto3" json:"promote_members_pending_pni_aci_profile_key,omitempty"` // change epoch = 5
|
||||||
ModifyMemberLabels []*GroupChange_Actions_ModifyMemberLabelAction `protobuf:"bytes,26,rep,name=modifyMemberLabels,proto3" json:"modifyMemberLabels,omitempty"` // change epoch = 6;
|
ModifyMemberLabels []*GroupChange_Actions_ModifyMemberLabelAction `protobuf:"bytes,26,rep,name=modifyMemberLabels,proto3" json:"modifyMemberLabels,omitempty"` // change epoch = 6;
|
||||||
ModifyMemberLabelAccess *GroupChange_Actions_ModifyMemberLabelAccessControlAction `protobuf:"bytes,27,opt,name=modifyMemberLabelAccess,proto3" json:"modifyMemberLabelAccess,omitempty"` // change epoch = 6
|
|
||||||
TerminateGroup *GroupChange_Actions_TerminateGroupAction `protobuf:"bytes,28,opt,name=terminate_group,json=terminateGroup,proto3" json:"terminate_group,omitempty"` // change epoch = 7
|
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
}
|
}
|
||||||
|
|
@ -1551,20 +1533,6 @@ func (x *GroupChange_Actions) GetModifyMemberLabels() []*GroupChange_Actions_Mod
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *GroupChange_Actions) GetModifyMemberLabelAccess() *GroupChange_Actions_ModifyMemberLabelAccessControlAction {
|
|
||||||
if x != nil {
|
|
||||||
return x.ModifyMemberLabelAccess
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *GroupChange_Actions) GetTerminateGroup() *GroupChange_Actions_TerminateGroupAction {
|
|
||||||
if x != nil {
|
|
||||||
return x.TerminateGroup
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type GroupChange_Actions_AddMemberAction struct {
|
type GroupChange_Actions_AddMemberAction struct {
|
||||||
state protoimpl.MessageState `protogen:"open.v1"`
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
Added *Member `protobuf:"bytes,1,opt,name=added,proto3" json:"added,omitempty"`
|
Added *Member `protobuf:"bytes,1,opt,name=added,proto3" json:"added,omitempty"`
|
||||||
|
|
@ -2585,50 +2553,6 @@ func (x *GroupChange_Actions_ModifyAddFromInviteLinkAccessControlAction) GetAddF
|
||||||
return AccessControl_UNKNOWN
|
return AccessControl_UNKNOWN
|
||||||
}
|
}
|
||||||
|
|
||||||
type GroupChange_Actions_ModifyMemberLabelAccessControlAction struct {
|
|
||||||
state protoimpl.MessageState `protogen:"open.v1"`
|
|
||||||
MemberLabelAccess AccessControl_AccessRequired `protobuf:"varint,1,opt,name=memberLabelAccess,proto3,enum=signal.AccessControl_AccessRequired" json:"memberLabelAccess,omitempty"`
|
|
||||||
unknownFields protoimpl.UnknownFields
|
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *GroupChange_Actions_ModifyMemberLabelAccessControlAction) Reset() {
|
|
||||||
*x = GroupChange_Actions_ModifyMemberLabelAccessControlAction{}
|
|
||||||
mi := &file_Groups_proto_msgTypes[38]
|
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *GroupChange_Actions_ModifyMemberLabelAccessControlAction) String() string {
|
|
||||||
return protoimpl.X.MessageStringOf(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*GroupChange_Actions_ModifyMemberLabelAccessControlAction) ProtoMessage() {}
|
|
||||||
|
|
||||||
func (x *GroupChange_Actions_ModifyMemberLabelAccessControlAction) ProtoReflect() protoreflect.Message {
|
|
||||||
mi := &file_Groups_proto_msgTypes[38]
|
|
||||||
if x != nil {
|
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
|
||||||
if ms.LoadMessageInfo() == nil {
|
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
return ms
|
|
||||||
}
|
|
||||||
return mi.MessageOf(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deprecated: Use GroupChange_Actions_ModifyMemberLabelAccessControlAction.ProtoReflect.Descriptor instead.
|
|
||||||
func (*GroupChange_Actions_ModifyMemberLabelAccessControlAction) Descriptor() ([]byte, []int) {
|
|
||||||
return file_Groups_proto_rawDescGZIP(), []int{10, 0, 21}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *GroupChange_Actions_ModifyMemberLabelAccessControlAction) GetMemberLabelAccess() AccessControl_AccessRequired {
|
|
||||||
if x != nil {
|
|
||||||
return x.MemberLabelAccess
|
|
||||||
}
|
|
||||||
return AccessControl_UNKNOWN
|
|
||||||
}
|
|
||||||
|
|
||||||
type GroupChange_Actions_ModifyInviteLinkPasswordAction struct {
|
type GroupChange_Actions_ModifyInviteLinkPasswordAction struct {
|
||||||
state protoimpl.MessageState `protogen:"open.v1"`
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
InviteLinkPassword []byte `protobuf:"bytes,1,opt,name=inviteLinkPassword,proto3" json:"inviteLinkPassword,omitempty"`
|
InviteLinkPassword []byte `protobuf:"bytes,1,opt,name=inviteLinkPassword,proto3" json:"inviteLinkPassword,omitempty"`
|
||||||
|
|
@ -2638,7 +2562,7 @@ type GroupChange_Actions_ModifyInviteLinkPasswordAction struct {
|
||||||
|
|
||||||
func (x *GroupChange_Actions_ModifyInviteLinkPasswordAction) Reset() {
|
func (x *GroupChange_Actions_ModifyInviteLinkPasswordAction) Reset() {
|
||||||
*x = GroupChange_Actions_ModifyInviteLinkPasswordAction{}
|
*x = GroupChange_Actions_ModifyInviteLinkPasswordAction{}
|
||||||
mi := &file_Groups_proto_msgTypes[39]
|
mi := &file_Groups_proto_msgTypes[38]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
|
|
@ -2650,7 +2574,7 @@ func (x *GroupChange_Actions_ModifyInviteLinkPasswordAction) String() string {
|
||||||
func (*GroupChange_Actions_ModifyInviteLinkPasswordAction) ProtoMessage() {}
|
func (*GroupChange_Actions_ModifyInviteLinkPasswordAction) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *GroupChange_Actions_ModifyInviteLinkPasswordAction) ProtoReflect() protoreflect.Message {
|
func (x *GroupChange_Actions_ModifyInviteLinkPasswordAction) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_Groups_proto_msgTypes[39]
|
mi := &file_Groups_proto_msgTypes[38]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
|
@ -2663,7 +2587,7 @@ func (x *GroupChange_Actions_ModifyInviteLinkPasswordAction) ProtoReflect() prot
|
||||||
|
|
||||||
// Deprecated: Use GroupChange_Actions_ModifyInviteLinkPasswordAction.ProtoReflect.Descriptor instead.
|
// Deprecated: Use GroupChange_Actions_ModifyInviteLinkPasswordAction.ProtoReflect.Descriptor instead.
|
||||||
func (*GroupChange_Actions_ModifyInviteLinkPasswordAction) Descriptor() ([]byte, []int) {
|
func (*GroupChange_Actions_ModifyInviteLinkPasswordAction) Descriptor() ([]byte, []int) {
|
||||||
return file_Groups_proto_rawDescGZIP(), []int{10, 0, 22}
|
return file_Groups_proto_rawDescGZIP(), []int{10, 0, 21}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *GroupChange_Actions_ModifyInviteLinkPasswordAction) GetInviteLinkPassword() []byte {
|
func (x *GroupChange_Actions_ModifyInviteLinkPasswordAction) GetInviteLinkPassword() []byte {
|
||||||
|
|
@ -2682,7 +2606,7 @@ type GroupChange_Actions_ModifyAnnouncementsOnlyAction struct {
|
||||||
|
|
||||||
func (x *GroupChange_Actions_ModifyAnnouncementsOnlyAction) Reset() {
|
func (x *GroupChange_Actions_ModifyAnnouncementsOnlyAction) Reset() {
|
||||||
*x = GroupChange_Actions_ModifyAnnouncementsOnlyAction{}
|
*x = GroupChange_Actions_ModifyAnnouncementsOnlyAction{}
|
||||||
mi := &file_Groups_proto_msgTypes[40]
|
mi := &file_Groups_proto_msgTypes[39]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
|
|
@ -2694,7 +2618,7 @@ func (x *GroupChange_Actions_ModifyAnnouncementsOnlyAction) String() string {
|
||||||
func (*GroupChange_Actions_ModifyAnnouncementsOnlyAction) ProtoMessage() {}
|
func (*GroupChange_Actions_ModifyAnnouncementsOnlyAction) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *GroupChange_Actions_ModifyAnnouncementsOnlyAction) ProtoReflect() protoreflect.Message {
|
func (x *GroupChange_Actions_ModifyAnnouncementsOnlyAction) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_Groups_proto_msgTypes[40]
|
mi := &file_Groups_proto_msgTypes[39]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
|
@ -2707,7 +2631,7 @@ func (x *GroupChange_Actions_ModifyAnnouncementsOnlyAction) ProtoReflect() proto
|
||||||
|
|
||||||
// Deprecated: Use GroupChange_Actions_ModifyAnnouncementsOnlyAction.ProtoReflect.Descriptor instead.
|
// Deprecated: Use GroupChange_Actions_ModifyAnnouncementsOnlyAction.ProtoReflect.Descriptor instead.
|
||||||
func (*GroupChange_Actions_ModifyAnnouncementsOnlyAction) Descriptor() ([]byte, []int) {
|
func (*GroupChange_Actions_ModifyAnnouncementsOnlyAction) Descriptor() ([]byte, []int) {
|
||||||
return file_Groups_proto_rawDescGZIP(), []int{10, 0, 23}
|
return file_Groups_proto_rawDescGZIP(), []int{10, 0, 22}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *GroupChange_Actions_ModifyAnnouncementsOnlyAction) GetAnnouncementsOnly() bool {
|
func (x *GroupChange_Actions_ModifyAnnouncementsOnlyAction) GetAnnouncementsOnly() bool {
|
||||||
|
|
@ -2717,42 +2641,6 @@ func (x *GroupChange_Actions_ModifyAnnouncementsOnlyAction) GetAnnouncementsOnly
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
type GroupChange_Actions_TerminateGroupAction struct {
|
|
||||||
state protoimpl.MessageState `protogen:"open.v1"`
|
|
||||||
unknownFields protoimpl.UnknownFields
|
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *GroupChange_Actions_TerminateGroupAction) Reset() {
|
|
||||||
*x = GroupChange_Actions_TerminateGroupAction{}
|
|
||||||
mi := &file_Groups_proto_msgTypes[41]
|
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *GroupChange_Actions_TerminateGroupAction) String() string {
|
|
||||||
return protoimpl.X.MessageStringOf(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*GroupChange_Actions_TerminateGroupAction) ProtoMessage() {}
|
|
||||||
|
|
||||||
func (x *GroupChange_Actions_TerminateGroupAction) ProtoReflect() protoreflect.Message {
|
|
||||||
mi := &file_Groups_proto_msgTypes[41]
|
|
||||||
if x != nil {
|
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
|
||||||
if ms.LoadMessageInfo() == nil {
|
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
return ms
|
|
||||||
}
|
|
||||||
return mi.MessageOf(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deprecated: Use GroupChange_Actions_TerminateGroupAction.ProtoReflect.Descriptor instead.
|
|
||||||
func (*GroupChange_Actions_TerminateGroupAction) Descriptor() ([]byte, []int) {
|
|
||||||
return file_Groups_proto_rawDescGZIP(), []int{10, 0, 24}
|
|
||||||
}
|
|
||||||
|
|
||||||
type GroupChanges_GroupChangeState struct {
|
type GroupChanges_GroupChangeState struct {
|
||||||
state protoimpl.MessageState `protogen:"open.v1"`
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
GroupChange *GroupChange `protobuf:"bytes,1,opt,name=groupChange,proto3" json:"groupChange,omitempty"`
|
GroupChange *GroupChange `protobuf:"bytes,1,opt,name=groupChange,proto3" json:"groupChange,omitempty"`
|
||||||
|
|
@ -2763,7 +2651,7 @@ type GroupChanges_GroupChangeState struct {
|
||||||
|
|
||||||
func (x *GroupChanges_GroupChangeState) Reset() {
|
func (x *GroupChanges_GroupChangeState) Reset() {
|
||||||
*x = GroupChanges_GroupChangeState{}
|
*x = GroupChanges_GroupChangeState{}
|
||||||
mi := &file_Groups_proto_msgTypes[42]
|
mi := &file_Groups_proto_msgTypes[40]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
|
|
@ -2775,7 +2663,7 @@ func (x *GroupChanges_GroupChangeState) String() string {
|
||||||
func (*GroupChanges_GroupChangeState) ProtoMessage() {}
|
func (*GroupChanges_GroupChangeState) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *GroupChanges_GroupChangeState) ProtoReflect() protoreflect.Message {
|
func (x *GroupChanges_GroupChangeState) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_Groups_proto_msgTypes[42]
|
mi := &file_Groups_proto_msgTypes[40]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
|
@ -2849,21 +2737,20 @@ const file_Groups_proto_rawDesc = "" +
|
||||||
"\ttimestamp\x18\x04 \x01(\x04R\ttimestamp\"D\n" +
|
"\ttimestamp\x18\x04 \x01(\x04R\ttimestamp\"D\n" +
|
||||||
"\fMemberBanned\x12\x16\n" +
|
"\fMemberBanned\x12\x16\n" +
|
||||||
"\x06userId\x18\x01 \x01(\fR\x06userId\x12\x1c\n" +
|
"\x06userId\x18\x01 \x01(\fR\x06userId\x12\x1c\n" +
|
||||||
"\ttimestamp\x18\x02 \x01(\x04R\ttimestamp\"\x8b\x03\n" +
|
"\ttimestamp\x18\x02 \x01(\x04R\ttimestamp\"\xc3\x02\n" +
|
||||||
"\rAccessControl\x12D\n" +
|
"\rAccessControl\x12D\n" +
|
||||||
"\n" +
|
"\n" +
|
||||||
"attributes\x18\x01 \x01(\x0e2$.signal.AccessControl.AccessRequiredR\n" +
|
"attributes\x18\x01 \x01(\x0e2$.signal.AccessControl.AccessRequiredR\n" +
|
||||||
"attributes\x12>\n" +
|
"attributes\x12>\n" +
|
||||||
"\amembers\x18\x02 \x01(\x0e2$.signal.AccessControl.AccessRequiredR\amembers\x12R\n" +
|
"\amembers\x18\x02 \x01(\x0e2$.signal.AccessControl.AccessRequiredR\amembers\x12R\n" +
|
||||||
"\x11addFromInviteLink\x18\x03 \x01(\x0e2$.signal.AccessControl.AccessRequiredR\x11addFromInviteLink\x12F\n" +
|
"\x11addFromInviteLink\x18\x03 \x01(\x0e2$.signal.AccessControl.AccessRequiredR\x11addFromInviteLink\"X\n" +
|
||||||
"\vmemberLabel\x18\x04 \x01(\x0e2$.signal.AccessControl.AccessRequiredR\vmemberLabel\"X\n" +
|
|
||||||
"\x0eAccessRequired\x12\v\n" +
|
"\x0eAccessRequired\x12\v\n" +
|
||||||
"\aUNKNOWN\x10\x00\x12\a\n" +
|
"\aUNKNOWN\x10\x00\x12\a\n" +
|
||||||
"\x03ANY\x10\x01\x12\n" +
|
"\x03ANY\x10\x01\x12\n" +
|
||||||
"\n" +
|
"\n" +
|
||||||
"\x06MEMBER\x10\x02\x12\x11\n" +
|
"\x06MEMBER\x10\x02\x12\x11\n" +
|
||||||
"\rADMINISTRATOR\x10\x03\x12\x11\n" +
|
"\rADMINISTRATOR\x10\x03\x12\x11\n" +
|
||||||
"\rUNSATISFIABLE\x10\x04\"\xb9\x05\n" +
|
"\rUNSATISFIABLE\x10\x04\"\x99\x05\n" +
|
||||||
"\x05Group\x12\x1c\n" +
|
"\x05Group\x12\x1c\n" +
|
||||||
"\tpublicKey\x18\x01 \x01(\fR\tpublicKey\x12\x14\n" +
|
"\tpublicKey\x18\x01 \x01(\fR\tpublicKey\x12\x14\n" +
|
||||||
"\x05title\x18\x02 \x01(\fR\x05title\x12 \n" +
|
"\x05title\x18\x02 \x01(\fR\x05title\x12 \n" +
|
||||||
|
|
@ -2878,10 +2765,7 @@ const file_Groups_proto_rawDesc = "" +
|
||||||
"\x12inviteLinkPassword\x18\n" +
|
"\x12inviteLinkPassword\x18\n" +
|
||||||
" \x01(\fR\x12inviteLinkPassword\x12-\n" +
|
" \x01(\fR\x12inviteLinkPassword\x12-\n" +
|
||||||
"\x12announcements_only\x18\f \x01(\bR\x11announcementsOnly\x12;\n" +
|
"\x12announcements_only\x18\f \x01(\bR\x11announcementsOnly\x12;\n" +
|
||||||
"\x0emembers_banned\x18\r \x03(\v2\x14.signal.MemberBannedR\rmembersBanned\x12\x1e\n" +
|
"\x0emembers_banned\x18\r \x03(\v2\x14.signal.MemberBannedR\rmembersBanned\"\xc3\x01\n" +
|
||||||
"\n" +
|
|
||||||
"terminated\x18\x0e \x01(\bR\n" +
|
|
||||||
"terminated\"\xc3\x01\n" +
|
|
||||||
"\x12GroupAttributeBlob\x12\x16\n" +
|
"\x12GroupAttributeBlob\x12\x16\n" +
|
||||||
"\x05title\x18\x01 \x01(\tH\x00R\x05title\x12\x18\n" +
|
"\x05title\x18\x01 \x01(\tH\x00R\x05title\x12\x18\n" +
|
||||||
"\x06avatar\x18\x02 \x01(\fH\x00R\x06avatar\x12D\n" +
|
"\x06avatar\x18\x02 \x01(\fH\x00R\x06avatar\x12D\n" +
|
||||||
|
|
@ -2905,11 +2789,11 @@ const file_Groups_proto_rawDesc = "" +
|
||||||
"\vmemberCount\x18\x04 \x01(\rR\vmemberCount\x12R\n" +
|
"\vmemberCount\x18\x04 \x01(\rR\vmemberCount\x12R\n" +
|
||||||
"\x11addFromInviteLink\x18\x05 \x01(\x0e2$.signal.AccessControl.AccessRequiredR\x11addFromInviteLink\x12\x18\n" +
|
"\x11addFromInviteLink\x18\x05 \x01(\x0e2$.signal.AccessControl.AccessRequiredR\x11addFromInviteLink\x12\x18\n" +
|
||||||
"\aversion\x18\x06 \x01(\rR\aversion\x122\n" +
|
"\aversion\x18\x06 \x01(\rR\aversion\x122\n" +
|
||||||
"\x14pendingAdminApproval\x18\a \x01(\bR\x14pendingAdminApproval\"\xa6*\n" +
|
"\x14pendingAdminApproval\x18\a \x01(\bR\x14pendingAdminApproval\"\xbb'\n" +
|
||||||
"\vGroupChange\x12\x18\n" +
|
"\vGroupChange\x12\x18\n" +
|
||||||
"\aactions\x18\x01 \x01(\fR\aactions\x12(\n" +
|
"\aactions\x18\x01 \x01(\fR\aactions\x12(\n" +
|
||||||
"\x0fserverSignature\x18\x02 \x01(\fR\x0fserverSignature\x12 \n" +
|
"\x0fserverSignature\x18\x02 \x01(\fR\x0fserverSignature\x12 \n" +
|
||||||
"\vchangeEpoch\x18\x03 \x01(\rR\vchangeEpoch\x1a\xb0)\n" +
|
"\vchangeEpoch\x18\x03 \x01(\rR\vchangeEpoch\x1a\xc5&\n" +
|
||||||
"\aActions\x12\"\n" +
|
"\aActions\x12\"\n" +
|
||||||
"\fsourceUserId\x18\x01 \x01(\fR\fsourceUserId\x12\x19\n" +
|
"\fsourceUserId\x18\x01 \x01(\fR\fsourceUserId\x12\x19\n" +
|
||||||
"\bgroup_id\x18\x19 \x01(\fR\agroupId\x12\x18\n" +
|
"\bgroup_id\x18\x19 \x01(\fR\agroupId\x12\x18\n" +
|
||||||
|
|
@ -2939,9 +2823,7 @@ const file_Groups_proto_rawDesc = "" +
|
||||||
"\x12add_members_banned\x18\x16 \x03(\v21.signal.GroupChange.Actions.AddMemberBannedActionR\x10addMembersBanned\x12h\n" +
|
"\x12add_members_banned\x18\x16 \x03(\v21.signal.GroupChange.Actions.AddMemberBannedActionR\x10addMembersBanned\x12h\n" +
|
||||||
"\x15delete_members_banned\x18\x17 \x03(\v24.signal.GroupChange.Actions.DeleteMemberBannedActionR\x13deleteMembersBanned\x12\xa2\x01\n" +
|
"\x15delete_members_banned\x18\x17 \x03(\v24.signal.GroupChange.Actions.DeleteMemberBannedActionR\x13deleteMembersBanned\x12\xa2\x01\n" +
|
||||||
"+promote_members_pending_pni_aci_profile_key\x18\x18 \x03(\v2F.signal.GroupChange.Actions.PromoteMemberPendingPniAciProfileKeyActionR%promoteMembersPendingPniAciProfileKey\x12c\n" +
|
"+promote_members_pending_pni_aci_profile_key\x18\x18 \x03(\v2F.signal.GroupChange.Actions.PromoteMemberPendingPniAciProfileKeyActionR%promoteMembersPendingPniAciProfileKey\x12c\n" +
|
||||||
"\x12modifyMemberLabels\x18\x1a \x03(\v23.signal.GroupChange.Actions.ModifyMemberLabelActionR\x12modifyMemberLabels\x12z\n" +
|
"\x12modifyMemberLabels\x18\x1a \x03(\v23.signal.GroupChange.Actions.ModifyMemberLabelActionR\x12modifyMemberLabels\x1ag\n" +
|
||||||
"\x17modifyMemberLabelAccess\x18\x1b \x01(\v2@.signal.GroupChange.Actions.ModifyMemberLabelAccessControlActionR\x17modifyMemberLabelAccess\x12Y\n" +
|
|
||||||
"\x0fterminate_group\x18\x1c \x01(\v20.signal.GroupChange.Actions.TerminateGroupActionR\x0eterminateGroup\x1ag\n" +
|
|
||||||
"\x0fAddMemberAction\x12$\n" +
|
"\x0fAddMemberAction\x12$\n" +
|
||||||
"\x05added\x18\x01 \x01(\v2\x0e.signal.MemberR\x05added\x12.\n" +
|
"\x05added\x18\x01 \x01(\v2\x0e.signal.MemberR\x05added\x12.\n" +
|
||||||
"\x12joinFromInviteLink\x18\x02 \x01(\bR\x12joinFromInviteLink\x1a:\n" +
|
"\x12joinFromInviteLink\x18\x02 \x01(\bR\x12joinFromInviteLink\x1a:\n" +
|
||||||
|
|
@ -3000,14 +2882,11 @@ const file_Groups_proto_rawDesc = "" +
|
||||||
" ModifyMembersAccessControlAction\x12J\n" +
|
" ModifyMembersAccessControlAction\x12J\n" +
|
||||||
"\rmembersAccess\x18\x01 \x01(\x0e2$.signal.AccessControl.AccessRequiredR\rmembersAccess\x1a\x8c\x01\n" +
|
"\rmembersAccess\x18\x01 \x01(\x0e2$.signal.AccessControl.AccessRequiredR\rmembersAccess\x1a\x8c\x01\n" +
|
||||||
"*ModifyAddFromInviteLinkAccessControlAction\x12^\n" +
|
"*ModifyAddFromInviteLinkAccessControlAction\x12^\n" +
|
||||||
"\x17addFromInviteLinkAccess\x18\x01 \x01(\x0e2$.signal.AccessControl.AccessRequiredR\x17addFromInviteLinkAccess\x1az\n" +
|
"\x17addFromInviteLinkAccess\x18\x01 \x01(\x0e2$.signal.AccessControl.AccessRequiredR\x17addFromInviteLinkAccess\x1aP\n" +
|
||||||
"$ModifyMemberLabelAccessControlAction\x12R\n" +
|
|
||||||
"\x11memberLabelAccess\x18\x01 \x01(\x0e2$.signal.AccessControl.AccessRequiredR\x11memberLabelAccess\x1aP\n" +
|
|
||||||
"\x1eModifyInviteLinkPasswordAction\x12.\n" +
|
"\x1eModifyInviteLinkPasswordAction\x12.\n" +
|
||||||
"\x12inviteLinkPassword\x18\x01 \x01(\fR\x12inviteLinkPassword\x1aN\n" +
|
"\x12inviteLinkPassword\x18\x01 \x01(\fR\x12inviteLinkPassword\x1aN\n" +
|
||||||
"\x1dModifyAnnouncementsOnlyAction\x12-\n" +
|
"\x1dModifyAnnouncementsOnlyAction\x12-\n" +
|
||||||
"\x12announcements_only\x18\x01 \x01(\bR\x11announcementsOnly\x1a\x16\n" +
|
"\x12announcements_only\x18\x01 \x01(\bR\x11announcementsOnly\"/\n" +
|
||||||
"\x14TerminateGroupAction\"/\n" +
|
|
||||||
"\x17ExternalGroupCredential\x12\x14\n" +
|
"\x17ExternalGroupCredential\x12\x14\n" +
|
||||||
"\x05token\x18\x01 \x01(\tR\x05token\"}\n" +
|
"\x05token\x18\x01 \x01(\tR\x05token\"}\n" +
|
||||||
"\rGroupResponse\x12#\n" +
|
"\rGroupResponse\x12#\n" +
|
||||||
|
|
@ -3039,7 +2918,7 @@ func file_Groups_proto_rawDescGZIP() []byte {
|
||||||
}
|
}
|
||||||
|
|
||||||
var file_Groups_proto_enumTypes = make([]protoimpl.EnumInfo, 2)
|
var file_Groups_proto_enumTypes = make([]protoimpl.EnumInfo, 2)
|
||||||
var file_Groups_proto_msgTypes = make([]protoimpl.MessageInfo, 43)
|
var file_Groups_proto_msgTypes = make([]protoimpl.MessageInfo, 41)
|
||||||
var file_Groups_proto_goTypes = []any{
|
var file_Groups_proto_goTypes = []any{
|
||||||
(Member_Role)(0), // 0: signal.Member.Role
|
(Member_Role)(0), // 0: signal.Member.Role
|
||||||
(AccessControl_AccessRequired)(0), // 1: signal.AccessControl.AccessRequired
|
(AccessControl_AccessRequired)(0), // 1: signal.AccessControl.AccessRequired
|
||||||
|
|
@ -3081,11 +2960,9 @@ var file_Groups_proto_goTypes = []any{
|
||||||
(*GroupChange_Actions_ModifyAttributesAccessControlAction)(nil), // 37: signal.GroupChange.Actions.ModifyAttributesAccessControlAction
|
(*GroupChange_Actions_ModifyAttributesAccessControlAction)(nil), // 37: signal.GroupChange.Actions.ModifyAttributesAccessControlAction
|
||||||
(*GroupChange_Actions_ModifyMembersAccessControlAction)(nil), // 38: signal.GroupChange.Actions.ModifyMembersAccessControlAction
|
(*GroupChange_Actions_ModifyMembersAccessControlAction)(nil), // 38: signal.GroupChange.Actions.ModifyMembersAccessControlAction
|
||||||
(*GroupChange_Actions_ModifyAddFromInviteLinkAccessControlAction)(nil), // 39: signal.GroupChange.Actions.ModifyAddFromInviteLinkAccessControlAction
|
(*GroupChange_Actions_ModifyAddFromInviteLinkAccessControlAction)(nil), // 39: signal.GroupChange.Actions.ModifyAddFromInviteLinkAccessControlAction
|
||||||
(*GroupChange_Actions_ModifyMemberLabelAccessControlAction)(nil), // 40: signal.GroupChange.Actions.ModifyMemberLabelAccessControlAction
|
(*GroupChange_Actions_ModifyInviteLinkPasswordAction)(nil), // 40: signal.GroupChange.Actions.ModifyInviteLinkPasswordAction
|
||||||
(*GroupChange_Actions_ModifyInviteLinkPasswordAction)(nil), // 41: signal.GroupChange.Actions.ModifyInviteLinkPasswordAction
|
(*GroupChange_Actions_ModifyAnnouncementsOnlyAction)(nil), // 41: signal.GroupChange.Actions.ModifyAnnouncementsOnlyAction
|
||||||
(*GroupChange_Actions_ModifyAnnouncementsOnlyAction)(nil), // 42: signal.GroupChange.Actions.ModifyAnnouncementsOnlyAction
|
(*GroupChanges_GroupChangeState)(nil), // 42: signal.GroupChanges.GroupChangeState
|
||||||
(*GroupChange_Actions_TerminateGroupAction)(nil), // 43: signal.GroupChange.Actions.TerminateGroupAction
|
|
||||||
(*GroupChanges_GroupChangeState)(nil), // 44: signal.GroupChanges.GroupChangeState
|
|
||||||
}
|
}
|
||||||
var file_Groups_proto_depIdxs = []int32{
|
var file_Groups_proto_depIdxs = []int32{
|
||||||
0, // 0: signal.Member.role:type_name -> signal.Member.Role
|
0, // 0: signal.Member.role:type_name -> signal.Member.Role
|
||||||
|
|
@ -3093,59 +2970,55 @@ var file_Groups_proto_depIdxs = []int32{
|
||||||
1, // 2: signal.AccessControl.attributes:type_name -> signal.AccessControl.AccessRequired
|
1, // 2: signal.AccessControl.attributes:type_name -> signal.AccessControl.AccessRequired
|
||||||
1, // 3: signal.AccessControl.members:type_name -> signal.AccessControl.AccessRequired
|
1, // 3: signal.AccessControl.members:type_name -> signal.AccessControl.AccessRequired
|
||||||
1, // 4: signal.AccessControl.addFromInviteLink:type_name -> signal.AccessControl.AccessRequired
|
1, // 4: signal.AccessControl.addFromInviteLink:type_name -> signal.AccessControl.AccessRequired
|
||||||
1, // 5: signal.AccessControl.memberLabel:type_name -> signal.AccessControl.AccessRequired
|
7, // 5: signal.Group.accessControl:type_name -> signal.AccessControl
|
||||||
7, // 6: signal.Group.accessControl:type_name -> signal.AccessControl
|
3, // 6: signal.Group.members:type_name -> signal.Member
|
||||||
3, // 7: signal.Group.members:type_name -> signal.Member
|
4, // 7: signal.Group.membersPendingProfileKey:type_name -> signal.MemberPendingProfileKey
|
||||||
4, // 8: signal.Group.membersPendingProfileKey:type_name -> signal.MemberPendingProfileKey
|
5, // 8: signal.Group.membersPendingAdminApproval:type_name -> signal.MemberPendingAdminApproval
|
||||||
5, // 9: signal.Group.membersPendingAdminApproval:type_name -> signal.MemberPendingAdminApproval
|
6, // 9: signal.Group.members_banned:type_name -> signal.MemberBanned
|
||||||
6, // 10: signal.Group.members_banned:type_name -> signal.MemberBanned
|
17, // 10: signal.GroupInviteLink.contentsV1:type_name -> signal.GroupInviteLink.GroupInviteLinkContentsV1
|
||||||
17, // 11: signal.GroupInviteLink.contentsV1:type_name -> signal.GroupInviteLink.GroupInviteLinkContentsV1
|
1, // 11: signal.GroupJoinInfo.addFromInviteLink:type_name -> signal.AccessControl.AccessRequired
|
||||||
1, // 12: signal.GroupJoinInfo.addFromInviteLink:type_name -> signal.AccessControl.AccessRequired
|
8, // 12: signal.GroupResponse.group:type_name -> signal.Group
|
||||||
8, // 13: signal.GroupResponse.group:type_name -> signal.Group
|
42, // 13: signal.GroupChanges.groupChanges:type_name -> signal.GroupChanges.GroupChangeState
|
||||||
44, // 14: signal.GroupChanges.groupChanges:type_name -> signal.GroupChanges.GroupChangeState
|
12, // 14: signal.GroupChangeResponse.group_change:type_name -> signal.GroupChange
|
||||||
12, // 15: signal.GroupChangeResponse.group_change:type_name -> signal.GroupChange
|
19, // 15: signal.GroupChange.Actions.addMembers:type_name -> signal.GroupChange.Actions.AddMemberAction
|
||||||
19, // 16: signal.GroupChange.Actions.addMembers:type_name -> signal.GroupChange.Actions.AddMemberAction
|
20, // 16: signal.GroupChange.Actions.deleteMembers:type_name -> signal.GroupChange.Actions.DeleteMemberAction
|
||||||
20, // 17: signal.GroupChange.Actions.deleteMembers:type_name -> signal.GroupChange.Actions.DeleteMemberAction
|
21, // 17: signal.GroupChange.Actions.modifyMemberRoles:type_name -> signal.GroupChange.Actions.ModifyMemberRoleAction
|
||||||
21, // 18: signal.GroupChange.Actions.modifyMemberRoles:type_name -> signal.GroupChange.Actions.ModifyMemberRoleAction
|
23, // 18: signal.GroupChange.Actions.modifyMemberProfileKeys:type_name -> signal.GroupChange.Actions.ModifyMemberProfileKeyAction
|
||||||
23, // 19: signal.GroupChange.Actions.modifyMemberProfileKeys:type_name -> signal.GroupChange.Actions.ModifyMemberProfileKeyAction
|
24, // 19: signal.GroupChange.Actions.addMembersPendingProfileKey:type_name -> signal.GroupChange.Actions.AddMemberPendingProfileKeyAction
|
||||||
24, // 20: signal.GroupChange.Actions.addMembersPendingProfileKey:type_name -> signal.GroupChange.Actions.AddMemberPendingProfileKeyAction
|
25, // 20: signal.GroupChange.Actions.deleteMembersPendingProfileKey:type_name -> signal.GroupChange.Actions.DeleteMemberPendingProfileKeyAction
|
||||||
25, // 21: signal.GroupChange.Actions.deleteMembersPendingProfileKey:type_name -> signal.GroupChange.Actions.DeleteMemberPendingProfileKeyAction
|
26, // 21: signal.GroupChange.Actions.promoteMembersPendingProfileKey:type_name -> signal.GroupChange.Actions.PromoteMemberPendingProfileKeyAction
|
||||||
26, // 22: signal.GroupChange.Actions.promoteMembersPendingProfileKey:type_name -> signal.GroupChange.Actions.PromoteMemberPendingProfileKeyAction
|
33, // 22: signal.GroupChange.Actions.modifyTitle:type_name -> signal.GroupChange.Actions.ModifyTitleAction
|
||||||
33, // 23: signal.GroupChange.Actions.modifyTitle:type_name -> signal.GroupChange.Actions.ModifyTitleAction
|
35, // 23: signal.GroupChange.Actions.modifyAvatar:type_name -> signal.GroupChange.Actions.ModifyAvatarAction
|
||||||
35, // 24: signal.GroupChange.Actions.modifyAvatar:type_name -> signal.GroupChange.Actions.ModifyAvatarAction
|
36, // 24: signal.GroupChange.Actions.modifyDisappearingMessageTimer:type_name -> signal.GroupChange.Actions.ModifyDisappearingMessageTimerAction
|
||||||
36, // 25: signal.GroupChange.Actions.modifyDisappearingMessageTimer:type_name -> signal.GroupChange.Actions.ModifyDisappearingMessageTimerAction
|
37, // 25: signal.GroupChange.Actions.modifyAttributesAccess:type_name -> signal.GroupChange.Actions.ModifyAttributesAccessControlAction
|
||||||
37, // 26: signal.GroupChange.Actions.modifyAttributesAccess:type_name -> signal.GroupChange.Actions.ModifyAttributesAccessControlAction
|
38, // 26: signal.GroupChange.Actions.modifyMemberAccess:type_name -> signal.GroupChange.Actions.ModifyMembersAccessControlAction
|
||||||
38, // 27: signal.GroupChange.Actions.modifyMemberAccess:type_name -> signal.GroupChange.Actions.ModifyMembersAccessControlAction
|
39, // 27: signal.GroupChange.Actions.modifyAddFromInviteLinkAccess:type_name -> signal.GroupChange.Actions.ModifyAddFromInviteLinkAccessControlAction
|
||||||
39, // 28: signal.GroupChange.Actions.modifyAddFromInviteLinkAccess:type_name -> signal.GroupChange.Actions.ModifyAddFromInviteLinkAccessControlAction
|
28, // 28: signal.GroupChange.Actions.addMembersPendingAdminApproval:type_name -> signal.GroupChange.Actions.AddMemberPendingAdminApprovalAction
|
||||||
28, // 29: signal.GroupChange.Actions.addMembersPendingAdminApproval:type_name -> signal.GroupChange.Actions.AddMemberPendingAdminApprovalAction
|
29, // 29: signal.GroupChange.Actions.deleteMembersPendingAdminApproval:type_name -> signal.GroupChange.Actions.DeleteMemberPendingAdminApprovalAction
|
||||||
29, // 30: signal.GroupChange.Actions.deleteMembersPendingAdminApproval:type_name -> signal.GroupChange.Actions.DeleteMemberPendingAdminApprovalAction
|
30, // 30: signal.GroupChange.Actions.promoteMembersPendingAdminApproval:type_name -> signal.GroupChange.Actions.PromoteMemberPendingAdminApprovalAction
|
||||||
30, // 31: signal.GroupChange.Actions.promoteMembersPendingAdminApproval:type_name -> signal.GroupChange.Actions.PromoteMemberPendingAdminApprovalAction
|
40, // 31: signal.GroupChange.Actions.modifyInviteLinkPassword:type_name -> signal.GroupChange.Actions.ModifyInviteLinkPasswordAction
|
||||||
41, // 32: signal.GroupChange.Actions.modifyInviteLinkPassword:type_name -> signal.GroupChange.Actions.ModifyInviteLinkPasswordAction
|
34, // 32: signal.GroupChange.Actions.modifyDescription:type_name -> signal.GroupChange.Actions.ModifyDescriptionAction
|
||||||
34, // 33: signal.GroupChange.Actions.modifyDescription:type_name -> signal.GroupChange.Actions.ModifyDescriptionAction
|
41, // 33: signal.GroupChange.Actions.modify_announcements_only:type_name -> signal.GroupChange.Actions.ModifyAnnouncementsOnlyAction
|
||||||
42, // 34: signal.GroupChange.Actions.modify_announcements_only:type_name -> signal.GroupChange.Actions.ModifyAnnouncementsOnlyAction
|
31, // 34: signal.GroupChange.Actions.add_members_banned:type_name -> signal.GroupChange.Actions.AddMemberBannedAction
|
||||||
31, // 35: signal.GroupChange.Actions.add_members_banned:type_name -> signal.GroupChange.Actions.AddMemberBannedAction
|
32, // 35: signal.GroupChange.Actions.delete_members_banned:type_name -> signal.GroupChange.Actions.DeleteMemberBannedAction
|
||||||
32, // 36: signal.GroupChange.Actions.delete_members_banned:type_name -> signal.GroupChange.Actions.DeleteMemberBannedAction
|
27, // 36: signal.GroupChange.Actions.promote_members_pending_pni_aci_profile_key:type_name -> signal.GroupChange.Actions.PromoteMemberPendingPniAciProfileKeyAction
|
||||||
27, // 37: signal.GroupChange.Actions.promote_members_pending_pni_aci_profile_key:type_name -> signal.GroupChange.Actions.PromoteMemberPendingPniAciProfileKeyAction
|
22, // 37: signal.GroupChange.Actions.modifyMemberLabels:type_name -> signal.GroupChange.Actions.ModifyMemberLabelAction
|
||||||
22, // 38: signal.GroupChange.Actions.modifyMemberLabels:type_name -> signal.GroupChange.Actions.ModifyMemberLabelAction
|
3, // 38: signal.GroupChange.Actions.AddMemberAction.added:type_name -> signal.Member
|
||||||
40, // 39: signal.GroupChange.Actions.modifyMemberLabelAccess:type_name -> signal.GroupChange.Actions.ModifyMemberLabelAccessControlAction
|
0, // 39: signal.GroupChange.Actions.ModifyMemberRoleAction.role:type_name -> signal.Member.Role
|
||||||
43, // 40: signal.GroupChange.Actions.terminate_group:type_name -> signal.GroupChange.Actions.TerminateGroupAction
|
4, // 40: signal.GroupChange.Actions.AddMemberPendingProfileKeyAction.added:type_name -> signal.MemberPendingProfileKey
|
||||||
3, // 41: signal.GroupChange.Actions.AddMemberAction.added:type_name -> signal.Member
|
5, // 41: signal.GroupChange.Actions.AddMemberPendingAdminApprovalAction.added:type_name -> signal.MemberPendingAdminApproval
|
||||||
0, // 42: signal.GroupChange.Actions.ModifyMemberRoleAction.role:type_name -> signal.Member.Role
|
0, // 42: signal.GroupChange.Actions.PromoteMemberPendingAdminApprovalAction.role:type_name -> signal.Member.Role
|
||||||
4, // 43: signal.GroupChange.Actions.AddMemberPendingProfileKeyAction.added:type_name -> signal.MemberPendingProfileKey
|
6, // 43: signal.GroupChange.Actions.AddMemberBannedAction.added:type_name -> signal.MemberBanned
|
||||||
5, // 44: signal.GroupChange.Actions.AddMemberPendingAdminApprovalAction.added:type_name -> signal.MemberPendingAdminApproval
|
1, // 44: signal.GroupChange.Actions.ModifyAttributesAccessControlAction.attributesAccess:type_name -> signal.AccessControl.AccessRequired
|
||||||
0, // 45: signal.GroupChange.Actions.PromoteMemberPendingAdminApprovalAction.role:type_name -> signal.Member.Role
|
1, // 45: signal.GroupChange.Actions.ModifyMembersAccessControlAction.membersAccess:type_name -> signal.AccessControl.AccessRequired
|
||||||
6, // 46: signal.GroupChange.Actions.AddMemberBannedAction.added:type_name -> signal.MemberBanned
|
1, // 46: signal.GroupChange.Actions.ModifyAddFromInviteLinkAccessControlAction.addFromInviteLinkAccess:type_name -> signal.AccessControl.AccessRequired
|
||||||
1, // 47: signal.GroupChange.Actions.ModifyAttributesAccessControlAction.attributesAccess:type_name -> signal.AccessControl.AccessRequired
|
12, // 47: signal.GroupChanges.GroupChangeState.groupChange:type_name -> signal.GroupChange
|
||||||
1, // 48: signal.GroupChange.Actions.ModifyMembersAccessControlAction.membersAccess:type_name -> signal.AccessControl.AccessRequired
|
8, // 48: signal.GroupChanges.GroupChangeState.groupState:type_name -> signal.Group
|
||||||
1, // 49: signal.GroupChange.Actions.ModifyAddFromInviteLinkAccessControlAction.addFromInviteLinkAccess:type_name -> signal.AccessControl.AccessRequired
|
49, // [49:49] is the sub-list for method output_type
|
||||||
1, // 50: signal.GroupChange.Actions.ModifyMemberLabelAccessControlAction.memberLabelAccess:type_name -> signal.AccessControl.AccessRequired
|
49, // [49:49] is the sub-list for method input_type
|
||||||
12, // 51: signal.GroupChanges.GroupChangeState.groupChange:type_name -> signal.GroupChange
|
49, // [49:49] is the sub-list for extension type_name
|
||||||
8, // 52: signal.GroupChanges.GroupChangeState.groupState:type_name -> signal.Group
|
49, // [49:49] is the sub-list for extension extendee
|
||||||
53, // [53:53] is the sub-list for method output_type
|
0, // [0:49] is the sub-list for field type_name
|
||||||
53, // [53:53] is the sub-list for method input_type
|
|
||||||
53, // [53:53] is the sub-list for extension type_name
|
|
||||||
53, // [53:53] is the sub-list for extension extendee
|
|
||||||
0, // [0:53] is the sub-list for field type_name
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() { file_Groups_proto_init() }
|
func init() { file_Groups_proto_init() }
|
||||||
|
|
@ -3168,7 +3041,7 @@ func file_Groups_proto_init() {
|
||||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
RawDescriptor: unsafe.Slice(unsafe.StringData(file_Groups_proto_rawDesc), len(file_Groups_proto_rawDesc)),
|
RawDescriptor: unsafe.Slice(unsafe.StringData(file_Groups_proto_rawDesc), len(file_Groups_proto_rawDesc)),
|
||||||
NumEnums: 2,
|
NumEnums: 2,
|
||||||
NumMessages: 43,
|
NumMessages: 41,
|
||||||
NumExtensions: 0,
|
NumExtensions: 0,
|
||||||
NumServices: 0,
|
NumServices: 0,
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -69,7 +69,6 @@ message AccessControl {
|
||||||
AccessRequired attributes = 1;
|
AccessRequired attributes = 1;
|
||||||
AccessRequired members = 2;
|
AccessRequired members = 2;
|
||||||
AccessRequired addFromInviteLink = 3;
|
AccessRequired addFromInviteLink = 3;
|
||||||
AccessRequired memberLabel = 4;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
message Group {
|
message Group {
|
||||||
|
|
@ -88,8 +87,7 @@ message Group {
|
||||||
bytes inviteLinkPassword = 10;
|
bytes inviteLinkPassword = 10;
|
||||||
bool announcements_only = 12;
|
bool announcements_only = 12;
|
||||||
repeated MemberBanned members_banned = 13;
|
repeated MemberBanned members_banned = 13;
|
||||||
bool terminated = 14;
|
// next: 14
|
||||||
// next: 15
|
|
||||||
}
|
}
|
||||||
|
|
||||||
message GroupAttributeBlob {
|
message GroupAttributeBlob {
|
||||||
|
|
@ -227,10 +225,6 @@ message GroupChange {
|
||||||
AccessControl.AccessRequired addFromInviteLinkAccess = 1;
|
AccessControl.AccessRequired addFromInviteLinkAccess = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
message ModifyMemberLabelAccessControlAction {
|
|
||||||
AccessControl.AccessRequired memberLabelAccess = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
message ModifyInviteLinkPasswordAction {
|
message ModifyInviteLinkPasswordAction {
|
||||||
bytes inviteLinkPassword = 1;
|
bytes inviteLinkPassword = 1;
|
||||||
}
|
}
|
||||||
|
|
@ -239,8 +233,6 @@ message GroupChange {
|
||||||
bool announcements_only = 1;
|
bool announcements_only = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
message TerminateGroupAction {}
|
|
||||||
|
|
||||||
bytes sourceUserId = 1;
|
bytes sourceUserId = 1;
|
||||||
// clients should not provide this value; the server will provide it in the response buffer to ensure the signature is binding to a particular group
|
// clients should not provide this value; the server will provide it in the response buffer to ensure the signature is binding to a particular group
|
||||||
// if clients set it during a request the server will respond with 400.
|
// if clients set it during a request the server will respond with 400.
|
||||||
|
|
@ -270,9 +262,7 @@ message GroupChange {
|
||||||
repeated DeleteMemberBannedAction delete_members_banned = 23; // change epoch = 4
|
repeated DeleteMemberBannedAction delete_members_banned = 23; // change epoch = 4
|
||||||
repeated PromoteMemberPendingPniAciProfileKeyAction promote_members_pending_pni_aci_profile_key = 24; // change epoch = 5
|
repeated PromoteMemberPendingPniAciProfileKeyAction promote_members_pending_pni_aci_profile_key = 24; // change epoch = 5
|
||||||
repeated ModifyMemberLabelAction modifyMemberLabels = 26; // change epoch = 6;
|
repeated ModifyMemberLabelAction modifyMemberLabels = 26; // change epoch = 6;
|
||||||
ModifyMemberLabelAccessControlAction modifyMemberLabelAccess = 27; // change epoch = 6
|
// next: 27
|
||||||
TerminateGroupAction terminate_group = 28; // change epoch = 7
|
|
||||||
// next: 29
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bytes actions = 1;
|
bytes actions = 1;
|
||||||
|
|
|
||||||
17
pkg/signalmeow/protobuf/Provisioning.pb.go
generated
17
pkg/signalmeow/protobuf/Provisioning.pb.go
generated
|
|
@ -5,7 +5,7 @@
|
||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// protoc-gen-go v1.36.11
|
// protoc-gen-go v1.36.11
|
||||||
// protoc v7.34.1
|
// protoc v6.33.5
|
||||||
// source: Provisioning.proto
|
// source: Provisioning.proto
|
||||||
|
|
||||||
package signalpb
|
package signalpb
|
||||||
|
|
@ -199,6 +199,7 @@ type ProvisionMessage struct {
|
||||||
ProfileKey []byte `protobuf:"bytes,6,opt,name=profileKey" json:"profileKey,omitempty"`
|
ProfileKey []byte `protobuf:"bytes,6,opt,name=profileKey" json:"profileKey,omitempty"`
|
||||||
ReadReceipts *bool `protobuf:"varint,7,opt,name=readReceipts" json:"readReceipts,omitempty"`
|
ReadReceipts *bool `protobuf:"varint,7,opt,name=readReceipts" json:"readReceipts,omitempty"`
|
||||||
ProvisioningVersion *uint32 `protobuf:"varint,9,opt,name=provisioningVersion" json:"provisioningVersion,omitempty"`
|
ProvisioningVersion *uint32 `protobuf:"varint,9,opt,name=provisioningVersion" json:"provisioningVersion,omitempty"`
|
||||||
|
MasterKey []byte `protobuf:"bytes,13,opt,name=masterKey" json:"masterKey,omitempty"` // Deprecated, but required by linked devices
|
||||||
EphemeralBackupKey []byte `protobuf:"bytes,14,opt,name=ephemeralBackupKey" json:"ephemeralBackupKey,omitempty"` // 32 bytes
|
EphemeralBackupKey []byte `protobuf:"bytes,14,opt,name=ephemeralBackupKey" json:"ephemeralBackupKey,omitempty"` // 32 bytes
|
||||||
AccountEntropyPool *string `protobuf:"bytes,15,opt,name=accountEntropyPool" json:"accountEntropyPool,omitempty"`
|
AccountEntropyPool *string `protobuf:"bytes,15,opt,name=accountEntropyPool" json:"accountEntropyPool,omitempty"`
|
||||||
MediaRootBackupKey []byte `protobuf:"bytes,16,opt,name=mediaRootBackupKey" json:"mediaRootBackupKey,omitempty"` // 32-bytes
|
MediaRootBackupKey []byte `protobuf:"bytes,16,opt,name=mediaRootBackupKey" json:"mediaRootBackupKey,omitempty"` // 32-bytes
|
||||||
|
|
@ -322,6 +323,13 @@ func (x *ProvisionMessage) GetProvisioningVersion() uint32 {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (x *ProvisionMessage) GetMasterKey() []byte {
|
||||||
|
if x != nil {
|
||||||
|
return x.MasterKey
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (x *ProvisionMessage) GetEphemeralBackupKey() []byte {
|
func (x *ProvisionMessage) GetEphemeralBackupKey() []byte {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.EphemeralBackupKey
|
return x.EphemeralBackupKey
|
||||||
|
|
@ -366,7 +374,7 @@ const file_Provisioning_proto_rawDesc = "" +
|
||||||
"\aaddress\x18\x01 \x01(\tR\aaddress\"E\n" +
|
"\aaddress\x18\x01 \x01(\tR\aaddress\"E\n" +
|
||||||
"\x11ProvisionEnvelope\x12\x1c\n" +
|
"\x11ProvisionEnvelope\x12\x1c\n" +
|
||||||
"\tpublicKey\x18\x01 \x01(\fR\tpublicKey\x12\x12\n" +
|
"\tpublicKey\x18\x01 \x01(\fR\tpublicKey\x12\x12\n" +
|
||||||
"\x04body\x18\x02 \x01(\fR\x04body\"\xb4\x05\n" +
|
"\x04body\x18\x02 \x01(\fR\x04body\"\xcc\x05\n" +
|
||||||
"\x10ProvisionMessage\x122\n" +
|
"\x10ProvisionMessage\x122\n" +
|
||||||
"\x14aciIdentityKeyPublic\x18\x01 \x01(\fR\x14aciIdentityKeyPublic\x124\n" +
|
"\x14aciIdentityKeyPublic\x18\x01 \x01(\fR\x14aciIdentityKeyPublic\x124\n" +
|
||||||
"\x15aciIdentityKeyPrivate\x18\x02 \x01(\fR\x15aciIdentityKeyPrivate\x122\n" +
|
"\x15aciIdentityKeyPrivate\x18\x02 \x01(\fR\x15aciIdentityKeyPrivate\x122\n" +
|
||||||
|
|
@ -382,12 +390,13 @@ const file_Provisioning_proto_rawDesc = "" +
|
||||||
"profileKey\x18\x06 \x01(\fR\n" +
|
"profileKey\x18\x06 \x01(\fR\n" +
|
||||||
"profileKey\x12\"\n" +
|
"profileKey\x12\"\n" +
|
||||||
"\freadReceipts\x18\a \x01(\bR\freadReceipts\x120\n" +
|
"\freadReceipts\x18\a \x01(\bR\freadReceipts\x120\n" +
|
||||||
"\x13provisioningVersion\x18\t \x01(\rR\x13provisioningVersion\x12.\n" +
|
"\x13provisioningVersion\x18\t \x01(\rR\x13provisioningVersion\x12\x1c\n" +
|
||||||
|
"\tmasterKey\x18\r \x01(\fR\tmasterKey\x12.\n" +
|
||||||
"\x12ephemeralBackupKey\x18\x0e \x01(\fR\x12ephemeralBackupKey\x12.\n" +
|
"\x12ephemeralBackupKey\x18\x0e \x01(\fR\x12ephemeralBackupKey\x12.\n" +
|
||||||
"\x12accountEntropyPool\x18\x0f \x01(\tR\x12accountEntropyPool\x12.\n" +
|
"\x12accountEntropyPool\x18\x0f \x01(\tR\x12accountEntropyPool\x12.\n" +
|
||||||
"\x12mediaRootBackupKey\x18\x10 \x01(\fR\x12mediaRootBackupKey\x12\x1c\n" +
|
"\x12mediaRootBackupKey\x18\x10 \x01(\fR\x12mediaRootBackupKey\x12\x1c\n" +
|
||||||
"\taciBinary\x18\x11 \x01(\fR\taciBinary\x12\x1c\n" +
|
"\taciBinary\x18\x11 \x01(\fR\taciBinary\x12\x1c\n" +
|
||||||
"\tpniBinary\x18\x12 \x01(\fR\tpniBinaryJ\x04\b\r\x10\x0e*G\n" +
|
"\tpniBinary\x18\x12 \x01(\fR\tpniBinary*G\n" +
|
||||||
"\x13ProvisioningVersion\x12\v\n" +
|
"\x13ProvisioningVersion\x12\v\n" +
|
||||||
"\aINITIAL\x10\x00\x12\x12\n" +
|
"\aINITIAL\x10\x00\x12\x12\n" +
|
||||||
"\x0eTABLET_SUPPORT\x10\x01\x12\v\n" +
|
"\x0eTABLET_SUPPORT\x10\x01\x12\v\n" +
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ message ProvisionMessage {
|
||||||
optional bytes profileKey = 6;
|
optional bytes profileKey = 6;
|
||||||
optional bool readReceipts = 7;
|
optional bool readReceipts = 7;
|
||||||
optional uint32 provisioningVersion = 9;
|
optional uint32 provisioningVersion = 9;
|
||||||
reserved /*masterKey*/ 13; // Deprecated in favor of accountEntropyPool
|
optional bytes masterKey = 13; // Deprecated, but required by linked devices
|
||||||
optional bytes ephemeralBackupKey = 14; // 32 bytes
|
optional bytes ephemeralBackupKey = 14; // 32 bytes
|
||||||
optional string accountEntropyPool = 15;
|
optional string accountEntropyPool = 15;
|
||||||
optional bytes mediaRootBackupKey = 16; // 32-bytes
|
optional bytes mediaRootBackupKey = 16; // 32-bytes
|
||||||
|
|
|
||||||
1348
pkg/signalmeow/protobuf/SignalService.pb.go
generated
1348
pkg/signalmeow/protobuf/SignalService.pb.go
generated
File diff suppressed because it is too large
Load diff
|
|
@ -13,79 +13,23 @@ option java_outer_classname = "SignalServiceProtos";
|
||||||
message Envelope {
|
message Envelope {
|
||||||
enum Type {
|
enum Type {
|
||||||
UNKNOWN = 0;
|
UNKNOWN = 0;
|
||||||
|
CIPHERTEXT = 1; // content => (version byte | SignalMessage{Content})
|
||||||
/**
|
|
||||||
* A double-ratchet message represents a "normal," "unsealed-sender" message
|
|
||||||
* encrypted using the Double Ratchet within an established Signal session.
|
|
||||||
* Double-ratchet messages include sender information in the plaintext
|
|
||||||
* portion of the `Envelope`.
|
|
||||||
*/
|
|
||||||
DOUBLE_RATCHET = 1; // content => (version byte | SignalMessage{Content})
|
|
||||||
|
|
||||||
reserved 2;
|
reserved 2;
|
||||||
reserved "KEY_EXCHANGE";
|
reserved "KEY_EXCHANGE";
|
||||||
|
PREKEY_BUNDLE = 3; // content => (version byte | PreKeySignalMessage{Content})
|
||||||
/**
|
SERVER_DELIVERY_RECEIPT = 5; // legacyMessage => [] AND content => []
|
||||||
* A prekey message begins a new Signal session. The `content` of a prekey
|
UNIDENTIFIED_SENDER = 6; // legacyMessage => [] AND content => ((version byte | UnidentifiedSenderMessage) OR (version byte | Multi-Recipient Sealed Sender Format))
|
||||||
* message is a superset of a double-ratchet message's `content` and
|
SENDERKEY_MESSAGE = 7; // legacyMessage => [] AND content => (version byte | SenderKeyMessage)
|
||||||
* contains the sender's identity public key and information identifying the
|
PLAINTEXT_CONTENT = 8; // legacyMessage => [] AND content => (marker byte | Content)
|
||||||
* pre-keys used in the message's ciphertext. Like double-ratchet messages,
|
|
||||||
* prekey messages contain sender information in the plaintext portion of
|
|
||||||
* the `Envelope`.
|
|
||||||
*/
|
|
||||||
PREKEY_MESSAGE = 3; // content => (version byte | PreKeySignalMessage{Content})
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Server delivery receipts are generated by the server when
|
|
||||||
* "unsealed-sender" messages are delivered to and acknowledged by the
|
|
||||||
* destination device. Server delivery receipts identify the sender in the
|
|
||||||
* plaintext portion of the `Envelope` and have no `content`. Note that
|
|
||||||
* receipts for sealed-sender messages are generated by clients as
|
|
||||||
* `UNIDENTIFIED_SENDER` messages.
|
|
||||||
*
|
|
||||||
* Note that, with server delivery receipts, the "client timestamp" on
|
|
||||||
* the envelope refers to the timestamp of the original message (i.e. the
|
|
||||||
* message the server just delivered) and not to the time of delivery. The
|
|
||||||
* "server timestamp" refers to the time of delivery.
|
|
||||||
*/
|
|
||||||
SERVER_DELIVERY_RECEIPT = 5; // content => []
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An unidentified sender message represents a message with no sender
|
|
||||||
* information in the plaintext portion of the `Envelope`. Unidentified
|
|
||||||
* sender messages always contain an additional `subtype` in their
|
|
||||||
* `content`. They may or may not be part of an existing Signal session
|
|
||||||
* (i.e. an unidentified sender message may have a "prekey message"
|
|
||||||
* subtype or may indicate an encryption error).
|
|
||||||
*/
|
|
||||||
UNIDENTIFIED_SENDER = 6; // content => ((version byte | UnidentifiedSenderMessage) OR (version byte | Multi-Recipient Sealed Sender Format))
|
|
||||||
|
|
||||||
reserved 7;
|
|
||||||
reserved "SENDERKEY_MESSAGE";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A plaintext message is used solely to convey encryption error receipts
|
|
||||||
* and never contains encrypted message content. Encryption error receipts
|
|
||||||
* must be delivered in plaintext because, encryption/decryption of a prior
|
|
||||||
* message failed and there is no reason to believe that
|
|
||||||
* encryption/decryption of subsequent messages with the same key material
|
|
||||||
* would succeed.
|
|
||||||
*
|
|
||||||
* Critically, plaintext messages never have "real" message content
|
|
||||||
* generated by users. Plaintext messages include sender information.
|
|
||||||
*/
|
|
||||||
PLAINTEXT_CONTENT = 8; // content => (marker byte | Content)
|
|
||||||
|
|
||||||
// next: 9
|
|
||||||
}
|
}
|
||||||
|
|
||||||
optional Type type = 1;
|
optional Type type = 1;
|
||||||
reserved 2; // formerly optional string sourceE164 = 2;
|
reserved 2; // formerly optional string sourceE164 = 2;
|
||||||
optional string sourceServiceId = 11;
|
optional string sourceServiceId = 11;
|
||||||
optional uint32 sourceDeviceId = 7;
|
optional uint32 sourceDevice = 7;
|
||||||
optional string destinationServiceId = 13;
|
optional string destinationServiceId = 13;
|
||||||
reserved 3; // formerly optional string relay = 3;
|
reserved 3; // formerly optional string relay = 3;
|
||||||
optional uint64 clientTimestamp = 5;
|
optional uint64 timestamp = 5;
|
||||||
reserved 6; // formerly optional bytes legacyMessage = 6; // Contains an encrypted DataMessage; this field could have been set historically for type 1 or 3 messages; no longer in use
|
reserved 6; // formerly optional bytes legacyMessage = 6; // Contains an encrypted DataMessage; this field could have been set historically for type 1 or 3 messages; no longer in use
|
||||||
optional bytes content = 8; // Contains an encrypted Content
|
optional bytes content = 8; // Contains an encrypted Content
|
||||||
optional string serverGuid = 9;
|
optional string serverGuid = 9;
|
||||||
|
|
@ -104,20 +48,17 @@ message Envelope {
|
||||||
}
|
}
|
||||||
|
|
||||||
message Content {
|
message Content {
|
||||||
oneof content {
|
optional DataMessage dataMessage = 1;
|
||||||
DataMessage dataMessage = 1;
|
optional SyncMessage syncMessage = 2;
|
||||||
SyncMessage syncMessage = 2;
|
optional CallMessage callMessage = 3;
|
||||||
CallMessage callMessage = 3;
|
optional NullMessage nullMessage = 4;
|
||||||
NullMessage nullMessage = 4;
|
optional ReceiptMessage receiptMessage = 5;
|
||||||
ReceiptMessage receiptMessage = 5;
|
optional TypingMessage typingMessage = 6;
|
||||||
TypingMessage typingMessage = 6;
|
|
||||||
bytes /* DecryptionErrorMessage */ decryptionErrorMessage = 8;
|
|
||||||
StoryMessage storyMessage = 9;
|
|
||||||
EditMessage editMessage = 11;
|
|
||||||
}
|
|
||||||
|
|
||||||
optional bytes /* SenderKeyDistributionMessage */ senderKeyDistributionMessage = 7;
|
optional bytes /* SenderKeyDistributionMessage */ senderKeyDistributionMessage = 7;
|
||||||
|
optional bytes /* DecryptionErrorMessage */ decryptionErrorMessage = 8;
|
||||||
|
optional StoryMessage storyMessage = 9;
|
||||||
optional PniSignatureMessage pniSignatureMessage = 10;
|
optional PniSignatureMessage pniSignatureMessage = 10;
|
||||||
|
optional EditMessage editMessage = 11;
|
||||||
}
|
}
|
||||||
|
|
||||||
message CallMessage {
|
message CallMessage {
|
||||||
|
|
@ -390,8 +331,8 @@ message DataMessage {
|
||||||
message PollVote {
|
message PollVote {
|
||||||
optional bytes targetAuthorAciBinary = 1;
|
optional bytes targetAuthorAciBinary = 1;
|
||||||
optional uint64 targetSentTimestamp = 2;
|
optional uint64 targetSentTimestamp = 2;
|
||||||
repeated uint32 optionIndexes = 3;
|
repeated uint32 optionIndexes = 3; // must be in the range [0, options.length) from the PollCreate
|
||||||
optional uint32 voteCount = 4;
|
optional uint32 voteCount = 4; // increment this by 1 each time you vote on a given poll
|
||||||
}
|
}
|
||||||
|
|
||||||
message PinMessage {
|
message PinMessage {
|
||||||
|
|
@ -408,11 +349,6 @@ message DataMessage {
|
||||||
optional uint64 targetSentTimestamp = 2;
|
optional uint64 targetSentTimestamp = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
message AdminDelete {
|
|
||||||
optional bytes targetAuthorAciBinary = 1; // 16-byte UUID
|
|
||||||
optional uint64 targetSentTimestamp = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
optional string body = 1;
|
optional string body = 1;
|
||||||
repeated AttachmentPointer attachments = 2;
|
repeated AttachmentPointer attachments = 2;
|
||||||
reserved /*groupV1*/ 3;
|
reserved /*groupV1*/ 3;
|
||||||
|
|
@ -440,8 +376,7 @@ message DataMessage {
|
||||||
optional PollVote pollVote = 26;
|
optional PollVote pollVote = 26;
|
||||||
optional PinMessage pinMessage = 27;
|
optional PinMessage pinMessage = 27;
|
||||||
optional UnpinMessage unpinMessage = 28;
|
optional UnpinMessage unpinMessage = 28;
|
||||||
optional AdminDelete adminDelete = 29;
|
// NEXT ID: 29
|
||||||
// NEXT ID: 30
|
|
||||||
}
|
}
|
||||||
|
|
||||||
message NullMessage {
|
message NullMessage {
|
||||||
|
|
@ -500,12 +435,6 @@ message TextAttachment {
|
||||||
}
|
}
|
||||||
|
|
||||||
message Gradient {
|
message Gradient {
|
||||||
// Color ordering:
|
|
||||||
// 0 degrees: bottom-to-top
|
|
||||||
// 90 degrees: left-to-right
|
|
||||||
// 180 degrees: top-to-bottom
|
|
||||||
// 270 degrees: right-to-left
|
|
||||||
|
|
||||||
optional uint32 startColor = 1; // deprecated: this field will be removed in a future release.
|
optional uint32 startColor = 1; // deprecated: this field will be removed in a future release.
|
||||||
optional uint32 endColor = 2; // deprecated: this field will be removed in a future release.
|
optional uint32 endColor = 2; // deprecated: this field will be removed in a future release.
|
||||||
optional uint32 angle = 3; // degrees
|
optional uint32 angle = 3; // degrees
|
||||||
|
|
@ -618,7 +547,7 @@ message SyncMessage {
|
||||||
optional bool unidentifiedDeliveryIndicators = 2;
|
optional bool unidentifiedDeliveryIndicators = 2;
|
||||||
optional bool typingIndicators = 3;
|
optional bool typingIndicators = 3;
|
||||||
reserved /* linkPreviews */ 4;
|
reserved /* linkPreviews */ 4;
|
||||||
reserved /* provisioningVersion */ 5;
|
optional uint32 provisioningVersion = 5;
|
||||||
optional bool linkPreviews = 6;
|
optional bool linkPreviews = 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -653,7 +582,7 @@ message SyncMessage {
|
||||||
|
|
||||||
message Keys {
|
message Keys {
|
||||||
reserved /* storageService */ 1;
|
reserved /* storageService */ 1;
|
||||||
reserved /* master */ 2;
|
optional bytes master = 2; // deprecated: this field will be removed in a future release.
|
||||||
optional string accountEntropyPool = 3;
|
optional string accountEntropyPool = 3;
|
||||||
optional bytes mediaRootBackupKey = 4;
|
optional bytes mediaRootBackupKey = 4;
|
||||||
}
|
}
|
||||||
|
|
@ -753,7 +682,7 @@ message SyncMessage {
|
||||||
optional bytes rootKey = 1;
|
optional bytes rootKey = 1;
|
||||||
optional bytes adminPasskey = 2;
|
optional bytes adminPasskey = 2;
|
||||||
optional Type type = 3; // defaults to UPDATE
|
optional Type type = 3; // defaults to UPDATE
|
||||||
reserved /*epoch*/ 4;
|
optional bytes epoch = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
message CallLogEvent {
|
message CallLogEvent {
|
||||||
|
|
@ -850,40 +779,31 @@ message SyncMessage {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
oneof content {
|
optional Sent sent = 1;
|
||||||
Sent sent = 1;
|
optional Contacts contacts = 2;
|
||||||
Contacts contacts = 2;
|
|
||||||
Request request = 4;
|
|
||||||
Blocked blocked = 6;
|
|
||||||
Verified verified = 7;
|
|
||||||
Configuration configuration = 9;
|
|
||||||
ViewOnceOpen viewOnceOpen = 11;
|
|
||||||
FetchLatest fetchLatest = 12;
|
|
||||||
Keys keys = 13;
|
|
||||||
MessageRequestResponse messageRequestResponse = 14;
|
|
||||||
OutgoingPayment outgoingPayment = 15;
|
|
||||||
PniChangeNumber pniChangeNumber = 18;
|
|
||||||
CallEvent callEvent = 19;
|
|
||||||
CallLinkUpdate callLinkUpdate = 20;
|
|
||||||
CallLogEvent callLogEvent = 21;
|
|
||||||
DeleteForMe deleteForMe = 22;
|
|
||||||
DeviceNameChange deviceNameChange = 23;
|
|
||||||
AttachmentBackfillRequest attachmentBackfillRequest = 24;
|
|
||||||
AttachmentBackfillResponse attachmentBackfillResponse = 25;
|
|
||||||
}
|
|
||||||
|
|
||||||
reserved /*groups*/ 3;
|
reserved /*groups*/ 3;
|
||||||
|
optional Request request = 4;
|
||||||
// Protobufs don't allow `repeated` fields to be inside of `oneof` so while
|
|
||||||
// the fields below are mutually exclusive with the rest of the values above
|
|
||||||
// we have to place them outside of `oneof`.
|
|
||||||
repeated Read read = 5;
|
repeated Read read = 5;
|
||||||
repeated StickerPackOperation stickerPackOperation = 10;
|
optional Blocked blocked = 6;
|
||||||
repeated Viewed viewed = 16;
|
optional Verified verified = 7;
|
||||||
|
optional Configuration configuration = 9;
|
||||||
reserved /*pniIdentity*/ 17;
|
|
||||||
|
|
||||||
optional bytes padding = 8;
|
optional bytes padding = 8;
|
||||||
|
repeated StickerPackOperation stickerPackOperation = 10;
|
||||||
|
optional ViewOnceOpen viewOnceOpen = 11;
|
||||||
|
optional FetchLatest fetchLatest = 12;
|
||||||
|
optional Keys keys = 13;
|
||||||
|
optional MessageRequestResponse messageRequestResponse = 14;
|
||||||
|
optional OutgoingPayment outgoingPayment = 15;
|
||||||
|
repeated Viewed viewed = 16;
|
||||||
|
reserved /*pniIdentity*/ 17;
|
||||||
|
optional PniChangeNumber pniChangeNumber = 18;
|
||||||
|
optional CallEvent callEvent = 19;
|
||||||
|
optional CallLinkUpdate callLinkUpdate = 20;
|
||||||
|
optional CallLogEvent callLogEvent = 21;
|
||||||
|
optional DeleteForMe deleteForMe = 22;
|
||||||
|
optional DeviceNameChange deviceNameChange = 23;
|
||||||
|
optional AttachmentBackfillRequest attachmentBackfillRequest = 24;
|
||||||
|
optional AttachmentBackfillResponse attachmentBackfillResponse = 25;
|
||||||
}
|
}
|
||||||
|
|
||||||
message AttachmentPointer {
|
message AttachmentPointer {
|
||||||
|
|
|
||||||
2
pkg/signalmeow/protobuf/StickerResources.pb.go
generated
2
pkg/signalmeow/protobuf/StickerResources.pb.go
generated
|
|
@ -6,7 +6,7 @@
|
||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// protoc-gen-go v1.36.11
|
// protoc-gen-go v1.36.11
|
||||||
// protoc v7.34.1
|
// protoc v6.33.5
|
||||||
// source: StickerResources.proto
|
// source: StickerResources.proto
|
||||||
|
|
||||||
package signalpb
|
package signalpb
|
||||||
|
|
|
||||||
43
pkg/signalmeow/protobuf/StorageService.pb.go
generated
43
pkg/signalmeow/protobuf/StorageService.pb.go
generated
|
|
@ -6,7 +6,7 @@
|
||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// protoc-gen-go v1.36.11
|
// protoc-gen-go v1.36.11
|
||||||
// protoc v7.34.1
|
// protoc v6.33.5
|
||||||
// source: StorageService.proto
|
// source: StorageService.proto
|
||||||
|
|
||||||
package signalpb
|
package signalpb
|
||||||
|
|
@ -1401,7 +1401,6 @@ type GroupV2Record struct {
|
||||||
HideStory bool `protobuf:"varint,8,opt,name=hideStory,proto3" json:"hideStory,omitempty"`
|
HideStory bool `protobuf:"varint,8,opt,name=hideStory,proto3" json:"hideStory,omitempty"`
|
||||||
StorySendMode GroupV2Record_StorySendMode `protobuf:"varint,10,opt,name=storySendMode,proto3,enum=signalservice.GroupV2Record_StorySendMode" json:"storySendMode,omitempty"`
|
StorySendMode GroupV2Record_StorySendMode `protobuf:"varint,10,opt,name=storySendMode,proto3,enum=signalservice.GroupV2Record_StorySendMode" json:"storySendMode,omitempty"`
|
||||||
AvatarColor *AvatarColor `protobuf:"varint,11,opt,name=avatarColor,proto3,enum=signalservice.AvatarColor,oneof" json:"avatarColor,omitempty"`
|
AvatarColor *AvatarColor `protobuf:"varint,11,opt,name=avatarColor,proto3,enum=signalservice.AvatarColor,oneof" json:"avatarColor,omitempty"`
|
||||||
VerifiedNameHash []byte `protobuf:"bytes,12,opt,name=verifiedNameHash,proto3" json:"verifiedNameHash,omitempty"` // SHA-256 of UTF-8 encoded decrypted group title that was last verified
|
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
}
|
}
|
||||||
|
|
@ -1506,13 +1505,6 @@ func (x *GroupV2Record) GetAvatarColor() AvatarColor {
|
||||||
return AvatarColor_A100
|
return AvatarColor_A100
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *GroupV2Record) GetVerifiedNameHash() []byte {
|
|
||||||
if x != nil {
|
|
||||||
return x.VerifiedNameHash
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type Payments struct {
|
type Payments struct {
|
||||||
state protoimpl.MessageState `protogen:"open.v1"`
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
Enabled bool `protobuf:"varint,1,opt,name=enabled,proto3" json:"enabled,omitempty"`
|
Enabled bool `protobuf:"varint,1,opt,name=enabled,proto3" json:"enabled,omitempty"`
|
||||||
|
|
@ -1606,7 +1598,6 @@ type AccountRecord struct {
|
||||||
NotificationProfileManualOverride *AccountRecord_NotificationProfileManualOverride `protobuf:"bytes,44,opt,name=notificationProfileManualOverride,proto3" json:"notificationProfileManualOverride,omitempty"`
|
NotificationProfileManualOverride *AccountRecord_NotificationProfileManualOverride `protobuf:"bytes,44,opt,name=notificationProfileManualOverride,proto3" json:"notificationProfileManualOverride,omitempty"`
|
||||||
NotificationProfileSyncDisabled bool `protobuf:"varint,45,opt,name=notificationProfileSyncDisabled,proto3" json:"notificationProfileSyncDisabled,omitempty"`
|
NotificationProfileSyncDisabled bool `protobuf:"varint,45,opt,name=notificationProfileSyncDisabled,proto3" json:"notificationProfileSyncDisabled,omitempty"`
|
||||||
AutomaticKeyVerificationDisabled bool `protobuf:"varint,46,opt,name=automaticKeyVerificationDisabled,proto3" json:"automaticKeyVerificationDisabled,omitempty"`
|
AutomaticKeyVerificationDisabled bool `protobuf:"varint,46,opt,name=automaticKeyVerificationDisabled,proto3" json:"automaticKeyVerificationDisabled,omitempty"`
|
||||||
HasSeenAdminDeleteEducationDialog bool `protobuf:"varint,47,opt,name=hasSeenAdminDeleteEducationDialog,proto3" json:"hasSeenAdminDeleteEducationDialog,omitempty"`
|
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
}
|
}
|
||||||
|
|
@ -1914,13 +1905,6 @@ func (x *AccountRecord) GetAutomaticKeyVerificationDisabled() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *AccountRecord) GetHasSeenAdminDeleteEducationDialog() bool {
|
|
||||||
if x != nil {
|
|
||||||
return x.HasSeenAdminDeleteEducationDialog
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
type StoryDistributionListRecord struct {
|
type StoryDistributionListRecord struct {
|
||||||
state protoimpl.MessageState `protogen:"open.v1"`
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
Identifier []byte `protobuf:"bytes,1,opt,name=identifier,proto3" json:"identifier,omitempty"`
|
Identifier []byte `protobuf:"bytes,1,opt,name=identifier,proto3" json:"identifier,omitempty"`
|
||||||
|
|
@ -2018,6 +2002,7 @@ type CallLinkRecord struct {
|
||||||
RootKey []byte `protobuf:"bytes,1,opt,name=rootKey,proto3" json:"rootKey,omitempty"`
|
RootKey []byte `protobuf:"bytes,1,opt,name=rootKey,proto3" json:"rootKey,omitempty"`
|
||||||
AdminPasskey []byte `protobuf:"bytes,2,opt,name=adminPasskey,proto3" json:"adminPasskey,omitempty"`
|
AdminPasskey []byte `protobuf:"bytes,2,opt,name=adminPasskey,proto3" json:"adminPasskey,omitempty"`
|
||||||
DeletedAtTimestampMs uint64 `protobuf:"varint,3,opt,name=deletedAtTimestampMs,proto3" json:"deletedAtTimestampMs,omitempty"`
|
DeletedAtTimestampMs uint64 `protobuf:"varint,3,opt,name=deletedAtTimestampMs,proto3" json:"deletedAtTimestampMs,omitempty"`
|
||||||
|
Epoch []byte `protobuf:"bytes,4,opt,name=epoch,proto3,oneof" json:"epoch,omitempty"`
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
}
|
}
|
||||||
|
|
@ -2073,6 +2058,13 @@ func (x *CallLinkRecord) GetDeletedAtTimestampMs() uint64 {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (x *CallLinkRecord) GetEpoch() []byte {
|
||||||
|
if x != nil {
|
||||||
|
return x.Epoch
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
type Recipient struct {
|
type Recipient struct {
|
||||||
state protoimpl.MessageState `protogen:"open.v1"`
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
// Types that are valid to be assigned to Identifier:
|
// Types that are valid to be assigned to Identifier:
|
||||||
|
|
@ -3203,7 +3195,7 @@ const file_StorageService_proto_rawDesc = "" +
|
||||||
"\vwhitelisted\x18\x03 \x01(\bR\vwhitelisted\x12\x1a\n" +
|
"\vwhitelisted\x18\x03 \x01(\bR\vwhitelisted\x12\x1a\n" +
|
||||||
"\barchived\x18\x04 \x01(\bR\barchived\x12\"\n" +
|
"\barchived\x18\x04 \x01(\bR\barchived\x12\"\n" +
|
||||||
"\fmarkedUnread\x18\x05 \x01(\bR\fmarkedUnread\x120\n" +
|
"\fmarkedUnread\x18\x05 \x01(\bR\fmarkedUnread\x120\n" +
|
||||||
"\x13mutedUntilTimestamp\x18\x06 \x01(\x04R\x13mutedUntilTimestamp\"\xcd\x04\n" +
|
"\x13mutedUntilTimestamp\x18\x06 \x01(\x04R\x13mutedUntilTimestamp\"\xa1\x04\n" +
|
||||||
"\rGroupV2Record\x12\x1c\n" +
|
"\rGroupV2Record\x12\x1c\n" +
|
||||||
"\tmasterKey\x18\x01 \x01(\fR\tmasterKey\x12\x18\n" +
|
"\tmasterKey\x18\x01 \x01(\fR\tmasterKey\x12\x18\n" +
|
||||||
"\ablocked\x18\x02 \x01(\bR\ablocked\x12 \n" +
|
"\ablocked\x18\x02 \x01(\bR\ablocked\x12 \n" +
|
||||||
|
|
@ -3215,8 +3207,7 @@ const file_StorageService_proto_rawDesc = "" +
|
||||||
"\thideStory\x18\b \x01(\bR\thideStory\x12P\n" +
|
"\thideStory\x18\b \x01(\bR\thideStory\x12P\n" +
|
||||||
"\rstorySendMode\x18\n" +
|
"\rstorySendMode\x18\n" +
|
||||||
" \x01(\x0e2*.signalservice.GroupV2Record.StorySendModeR\rstorySendMode\x12A\n" +
|
" \x01(\x0e2*.signalservice.GroupV2Record.StorySendModeR\rstorySendMode\x12A\n" +
|
||||||
"\vavatarColor\x18\v \x01(\x0e2\x1a.signalservice.AvatarColorH\x00R\vavatarColor\x88\x01\x01\x12*\n" +
|
"\vavatarColor\x18\v \x01(\x0e2\x1a.signalservice.AvatarColorH\x00R\vavatarColor\x88\x01\x01\"7\n" +
|
||||||
"\x10verifiedNameHash\x18\f \x01(\fR\x10verifiedNameHash\"7\n" +
|
|
||||||
"\rStorySendMode\x12\v\n" +
|
"\rStorySendMode\x12\v\n" +
|
||||||
"\aDEFAULT\x10\x00\x12\f\n" +
|
"\aDEFAULT\x10\x00\x12\f\n" +
|
||||||
"\bDISABLED\x10\x01\x12\v\n" +
|
"\bDISABLED\x10\x01\x12\v\n" +
|
||||||
|
|
@ -3225,7 +3216,7 @@ const file_StorageService_proto_rawDesc = "" +
|
||||||
"\">\n" +
|
"\">\n" +
|
||||||
"\bPayments\x12\x18\n" +
|
"\bPayments\x12\x18\n" +
|
||||||
"\aenabled\x18\x01 \x01(\bR\aenabled\x12\x18\n" +
|
"\aenabled\x18\x01 \x01(\bR\aenabled\x12\x18\n" +
|
||||||
"\aentropy\x18\x02 \x01(\fR\aentropy\"\x99\x1d\n" +
|
"\aentropy\x18\x02 \x01(\fR\aentropy\"\xcb\x1c\n" +
|
||||||
"\rAccountRecord\x12\x1e\n" +
|
"\rAccountRecord\x12\x1e\n" +
|
||||||
"\n" +
|
"\n" +
|
||||||
"profileKey\x18\x01 \x01(\fR\n" +
|
"profileKey\x18\x01 \x01(\fR\n" +
|
||||||
|
|
@ -3272,8 +3263,7 @@ const file_StorageService_proto_rawDesc = "" +
|
||||||
"\x11backupTierHistory\x18+ \x01(\v2..signalservice.AccountRecord.BackupTierHistoryR\x11backupTierHistory\x12\x8c\x01\n" +
|
"\x11backupTierHistory\x18+ \x01(\v2..signalservice.AccountRecord.BackupTierHistoryR\x11backupTierHistory\x12\x8c\x01\n" +
|
||||||
"!notificationProfileManualOverride\x18, \x01(\v2>.signalservice.AccountRecord.NotificationProfileManualOverrideR!notificationProfileManualOverride\x12H\n" +
|
"!notificationProfileManualOverride\x18, \x01(\v2>.signalservice.AccountRecord.NotificationProfileManualOverrideR!notificationProfileManualOverride\x12H\n" +
|
||||||
"\x1fnotificationProfileSyncDisabled\x18- \x01(\bR\x1fnotificationProfileSyncDisabled\x12J\n" +
|
"\x1fnotificationProfileSyncDisabled\x18- \x01(\bR\x1fnotificationProfileSyncDisabled\x12J\n" +
|
||||||
" automaticKeyVerificationDisabled\x18. \x01(\bR automaticKeyVerificationDisabled\x12L\n" +
|
" automaticKeyVerificationDisabled\x18. \x01(\bR automaticKeyVerificationDisabled\x1a\xb0\x02\n" +
|
||||||
"!hasSeenAdminDeleteEducationDialog\x18/ \x01(\bR!hasSeenAdminDeleteEducationDialog\x1a\xb0\x02\n" +
|
|
||||||
"\x12PinnedConversation\x12S\n" +
|
"\x12PinnedConversation\x12S\n" +
|
||||||
"\acontact\x18\x01 \x01(\v27.signalservice.AccountRecord.PinnedConversation.ContactH\x00R\acontact\x12&\n" +
|
"\acontact\x18\x01 \x01(\v27.signalservice.AccountRecord.PinnedConversation.ContactH\x00R\acontact\x12&\n" +
|
||||||
"\rlegacyGroupId\x18\x03 \x01(\fH\x00R\rlegacyGroupId\x12(\n" +
|
"\rlegacyGroupId\x18\x03 \x01(\fH\x00R\rlegacyGroupId\x12(\n" +
|
||||||
|
|
@ -3339,11 +3329,13 @@ const file_StorageService_proto_rawDesc = "" +
|
||||||
"\x12deletedAtTimestamp\x18\x04 \x01(\x04R\x12deletedAtTimestamp\x12$\n" +
|
"\x12deletedAtTimestamp\x18\x04 \x01(\x04R\x12deletedAtTimestamp\x12$\n" +
|
||||||
"\rallowsReplies\x18\x05 \x01(\bR\rallowsReplies\x12 \n" +
|
"\rallowsReplies\x18\x05 \x01(\bR\rallowsReplies\x12 \n" +
|
||||||
"\visBlockList\x18\x06 \x01(\bR\visBlockList\x12<\n" +
|
"\visBlockList\x18\x06 \x01(\bR\visBlockList\x12<\n" +
|
||||||
"\x19recipientServiceIdsBinary\x18\a \x03(\fR\x19recipientServiceIdsBinary\"\x88\x01\n" +
|
"\x19recipientServiceIdsBinary\x18\a \x03(\fR\x19recipientServiceIdsBinary\"\xa7\x01\n" +
|
||||||
"\x0eCallLinkRecord\x12\x18\n" +
|
"\x0eCallLinkRecord\x12\x18\n" +
|
||||||
"\arootKey\x18\x01 \x01(\fR\arootKey\x12\"\n" +
|
"\arootKey\x18\x01 \x01(\fR\arootKey\x12\"\n" +
|
||||||
"\fadminPasskey\x18\x02 \x01(\fR\fadminPasskey\x122\n" +
|
"\fadminPasskey\x18\x02 \x01(\fR\fadminPasskey\x122\n" +
|
||||||
"\x14deletedAtTimestampMs\x18\x03 \x01(\x04R\x14deletedAtTimestampMsJ\x04\b\x04\x10\x05\"\x90\x02\n" +
|
"\x14deletedAtTimestampMs\x18\x03 \x01(\x04R\x14deletedAtTimestampMs\x12\x19\n" +
|
||||||
|
"\x05epoch\x18\x04 \x01(\fH\x00R\x05epoch\x88\x01\x01B\b\n" +
|
||||||
|
"\x06_epoch\"\x90\x02\n" +
|
||||||
"\tRecipient\x12<\n" +
|
"\tRecipient\x12<\n" +
|
||||||
"\acontact\x18\x01 \x01(\v2 .signalservice.Recipient.ContactH\x00R\acontact\x12&\n" +
|
"\acontact\x18\x01 \x01(\v2 .signalservice.Recipient.ContactH\x00R\acontact\x12&\n" +
|
||||||
"\rlegacyGroupId\x18\x02 \x01(\fH\x00R\rlegacyGroupId\x12(\n" +
|
"\rlegacyGroupId\x18\x02 \x01(\fH\x00R\rlegacyGroupId\x12(\n" +
|
||||||
|
|
@ -3539,6 +3531,7 @@ func file_StorageService_proto_init() {
|
||||||
file_StorageService_proto_msgTypes[7].OneofWrappers = []any{}
|
file_StorageService_proto_msgTypes[7].OneofWrappers = []any{}
|
||||||
file_StorageService_proto_msgTypes[9].OneofWrappers = []any{}
|
file_StorageService_proto_msgTypes[9].OneofWrappers = []any{}
|
||||||
file_StorageService_proto_msgTypes[11].OneofWrappers = []any{}
|
file_StorageService_proto_msgTypes[11].OneofWrappers = []any{}
|
||||||
|
file_StorageService_proto_msgTypes[13].OneofWrappers = []any{}
|
||||||
file_StorageService_proto_msgTypes[14].OneofWrappers = []any{
|
file_StorageService_proto_msgTypes[14].OneofWrappers = []any{
|
||||||
(*Recipient_Contact_)(nil),
|
(*Recipient_Contact_)(nil),
|
||||||
(*Recipient_LegacyGroupId)(nil),
|
(*Recipient_LegacyGroupId)(nil),
|
||||||
|
|
|
||||||
|
|
@ -172,7 +172,6 @@ message GroupV2Record {
|
||||||
reserved /* storySendEnabled */ 9;
|
reserved /* storySendEnabled */ 9;
|
||||||
StorySendMode storySendMode = 10;
|
StorySendMode storySendMode = 10;
|
||||||
optional AvatarColor avatarColor = 11;
|
optional AvatarColor avatarColor = 11;
|
||||||
bytes verifiedNameHash = 12; // SHA-256 of UTF-8 encoded decrypted group title that was last verified
|
|
||||||
}
|
}
|
||||||
|
|
||||||
message Payments {
|
message Payments {
|
||||||
|
|
@ -297,7 +296,6 @@ message AccountRecord {
|
||||||
NotificationProfileManualOverride notificationProfileManualOverride = 44;
|
NotificationProfileManualOverride notificationProfileManualOverride = 44;
|
||||||
bool notificationProfileSyncDisabled = 45;
|
bool notificationProfileSyncDisabled = 45;
|
||||||
bool automaticKeyVerificationDisabled = 46;
|
bool automaticKeyVerificationDisabled = 46;
|
||||||
bool hasSeenAdminDeleteEducationDialog = 47;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
message StoryDistributionListRecord {
|
message StoryDistributionListRecord {
|
||||||
|
|
@ -314,7 +312,7 @@ message CallLinkRecord {
|
||||||
bytes rootKey = 1;
|
bytes rootKey = 1;
|
||||||
bytes adminPasskey = 2;
|
bytes adminPasskey = 2;
|
||||||
uint64 deletedAtTimestampMs = 3;
|
uint64 deletedAtTimestampMs = 3;
|
||||||
reserved 4; // was epoch field, never used
|
optional bytes epoch = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
message Recipient {
|
message Recipient {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// protoc-gen-go v1.36.11
|
// protoc-gen-go v1.36.11
|
||||||
// protoc v7.34.1
|
// protoc v6.33.5
|
||||||
// source: UnidentifiedDelivery.proto
|
// source: UnidentifiedDelivery.proto
|
||||||
|
|
||||||
// Copyright 2018 Signal Messenger, LLC
|
// Copyright 2018 Signal Messenger, LLC
|
||||||
|
|
|
||||||
2
pkg/signalmeow/protobuf/WebSocketResources.pb.go
generated
2
pkg/signalmeow/protobuf/WebSocketResources.pb.go
generated
|
|
@ -6,7 +6,7 @@
|
||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// protoc-gen-go v1.36.11
|
// protoc-gen-go v1.36.11
|
||||||
// protoc v7.34.1
|
// protoc v6.33.5
|
||||||
// source: WebSocketResources.proto
|
// source: WebSocketResources.proto
|
||||||
|
|
||||||
package signalpb
|
package signalpb
|
||||||
|
|
|
||||||
1398
pkg/signalmeow/protobuf/backuppb/Backup.pb.go
generated
1398
pkg/signalmeow/protobuf/backuppb/Backup.pb.go
generated
File diff suppressed because it is too large
Load diff
|
|
@ -2,7 +2,7 @@ syntax = "proto3";
|
||||||
|
|
||||||
package signal.backup;
|
package signal.backup;
|
||||||
|
|
||||||
option java_package = "org.signal.archive.proto";
|
option java_package = "org.thoughtcrime.securesms.backup.v2.proto";
|
||||||
option swift_prefix = "BackupProto_";
|
option swift_prefix = "BackupProto_";
|
||||||
|
|
||||||
message BackupInfo {
|
message BackupInfo {
|
||||||
|
|
@ -135,7 +135,6 @@ message AccountData {
|
||||||
CallsUseLessDataSetting callsUseLessDataSetting = 29; // If unset, treat the same as "Unknown" case
|
CallsUseLessDataSetting callsUseLessDataSetting = 29; // If unset, treat the same as "Unknown" case
|
||||||
bool allowSealedSenderFromAnyone = 30;
|
bool allowSealedSenderFromAnyone = 30;
|
||||||
bool allowAutomaticKeyVerification = 31;
|
bool allowAutomaticKeyVerification = 31;
|
||||||
bool hasSeenAdminDeleteEducationDialog = 32;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
message SubscriberData {
|
message SubscriberData {
|
||||||
|
|
@ -308,7 +307,6 @@ message Group {
|
||||||
bytes inviteLinkPassword = 10;
|
bytes inviteLinkPassword = 10;
|
||||||
bool announcements_only = 12;
|
bool announcements_only = 12;
|
||||||
repeated MemberBanned members_banned = 13;
|
repeated MemberBanned members_banned = 13;
|
||||||
bool terminated = 14;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
message GroupAttributeBlob {
|
message GroupAttributeBlob {
|
||||||
|
|
@ -333,8 +331,6 @@ message Group {
|
||||||
reserved /*profileKey*/ 3; // This field is ignored in Backups, in favor of Contact frames for members
|
reserved /*profileKey*/ 3; // This field is ignored in Backups, in favor of Contact frames for members
|
||||||
reserved /*presentation*/ 4; // This field is deprecated in the context of static group state
|
reserved /*presentation*/ 4; // This field is deprecated in the context of static group state
|
||||||
uint32 joinedAtVersion = 5;
|
uint32 joinedAtVersion = 5;
|
||||||
string labelEmoji = 6;
|
|
||||||
string labelString = 7;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
message MemberPendingProfileKey {
|
message MemberPendingProfileKey {
|
||||||
|
|
@ -367,7 +363,6 @@ message Group {
|
||||||
AccessRequired attributes = 1;
|
AccessRequired attributes = 1;
|
||||||
AccessRequired members = 2;
|
AccessRequired members = 2;
|
||||||
AccessRequired addFromInviteLink = 3;
|
AccessRequired addFromInviteLink = 3;
|
||||||
AccessRequired memberLabel = 4;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -410,7 +405,7 @@ message CallLink {
|
||||||
string name = 3;
|
string name = 3;
|
||||||
Restrictions restrictions = 4;
|
Restrictions restrictions = 4;
|
||||||
uint64 expirationMs = 5;
|
uint64 expirationMs = 5;
|
||||||
reserved /*epoch*/ 6;
|
optional bytes epoch = 6; // May be absent/empty for older links
|
||||||
}
|
}
|
||||||
|
|
||||||
message AdHocCall {
|
message AdHocCall {
|
||||||
|
|
@ -503,7 +498,6 @@ message ChatItem {
|
||||||
ViewOnceMessage viewOnceMessage = 18;
|
ViewOnceMessage viewOnceMessage = 18;
|
||||||
DirectStoryReplyMessage directStoryReplyMessage = 19; // group story reply messages are not backed up
|
DirectStoryReplyMessage directStoryReplyMessage = 19; // group story reply messages are not backed up
|
||||||
Poll poll = 20;
|
Poll poll = 20;
|
||||||
AdminDeletedMessage adminDeletedMessage = 22;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PinDetails pinDetails = 21; // only set if message is pinned
|
PinDetails pinDetails = 21; // only set if message is pinned
|
||||||
|
|
@ -904,10 +898,6 @@ message Poll {
|
||||||
repeated Reaction reactions = 5;
|
repeated Reaction reactions = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
message AdminDeletedMessage {
|
|
||||||
uint64 adminId = 1; // id of the admin that deleted the message
|
|
||||||
}
|
|
||||||
|
|
||||||
message ChatUpdateMessage {
|
message ChatUpdateMessage {
|
||||||
// If unset, importers should ignore the update message without throwing an error.
|
// If unset, importers should ignore the update message without throwing an error.
|
||||||
oneof update {
|
oneof update {
|
||||||
|
|
@ -1078,8 +1068,6 @@ message GroupChangeChatUpdate {
|
||||||
GroupV2MigrationDroppedMembersUpdate groupV2MigrationDroppedMembersUpdate = 32;
|
GroupV2MigrationDroppedMembersUpdate groupV2MigrationDroppedMembersUpdate = 32;
|
||||||
GroupSequenceOfRequestsAndCancelsUpdate groupSequenceOfRequestsAndCancelsUpdate = 33;
|
GroupSequenceOfRequestsAndCancelsUpdate groupSequenceOfRequestsAndCancelsUpdate = 33;
|
||||||
GroupExpirationTimerUpdate groupExpirationTimerUpdate = 34;
|
GroupExpirationTimerUpdate groupExpirationTimerUpdate = 34;
|
||||||
GroupMemberLabelAccessLevelChangeUpdate groupMemberLabelAccessLevelChangeUpdate = 35;
|
|
||||||
GroupTerminateChangeUpdate groupTerminateChangeUpdate = 36;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1131,15 +1119,6 @@ message GroupAttributesAccessLevelChangeUpdate {
|
||||||
GroupV2AccessLevel accessLevel = 2;
|
GroupV2AccessLevel accessLevel = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
message GroupMemberLabelAccessLevelChangeUpdate {
|
|
||||||
optional bytes updaterAci = 1;
|
|
||||||
GroupV2AccessLevel accessLevel = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
message GroupTerminateChangeUpdate {
|
|
||||||
optional bytes updaterAci = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
message GroupAnnouncementOnlyChangeUpdate {
|
message GroupAnnouncementOnlyChangeUpdate {
|
||||||
optional bytes updaterAci = 1;
|
optional bytes updaterAci = 1;
|
||||||
bool isAnnouncementOnly = 2;
|
bool isAnnouncementOnly = 2;
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
ANDROID_GIT_REVISION=${1:-439760e7732585bfd078d92d93732c04cc31e29e}
|
ANDROID_GIT_REVISION=${1:-bc6114f6e0d3a4b1dcdc472331505f2644185264}
|
||||||
DESKTOP_GIT_REVISION=${1:-1b2a3e7b283c32c5654a39da12fc04139fd26dbd}
|
DESKTOP_GIT_REVISION=${1:-a9063ec0c3c1079072c1e30e0749c1ae8be5500a}
|
||||||
|
|
||||||
update_proto() {
|
update_proto() {
|
||||||
case "$1" in
|
case "$1" in
|
||||||
|
|
@ -11,9 +11,9 @@ update_proto() {
|
||||||
prefix="lib/libsignal-service/src/main/protowire/"
|
prefix="lib/libsignal-service/src/main/protowire/"
|
||||||
GIT_REVISION=$ANDROID_GIT_REVISION
|
GIT_REVISION=$ANDROID_GIT_REVISION
|
||||||
;;
|
;;
|
||||||
Signal-Android-Archive)
|
Signal-Android-App)
|
||||||
REPO="Signal-Android"
|
REPO="Signal-Android"
|
||||||
prefix="lib/archive/src/main/protowire/"
|
prefix="app/src/main/protowire/"
|
||||||
GIT_REVISION=$ANDROID_GIT_REVISION
|
GIT_REVISION=$ANDROID_GIT_REVISION
|
||||||
;;
|
;;
|
||||||
Signal-Desktop)
|
Signal-Desktop)
|
||||||
|
|
@ -34,10 +34,11 @@ update_proto Signal-Android StickerResources.proto
|
||||||
update_proto Signal-Android WebSocketResources.proto
|
update_proto Signal-Android WebSocketResources.proto
|
||||||
update_proto Signal-Android StorageService.proto
|
update_proto Signal-Android StorageService.proto
|
||||||
|
|
||||||
update_proto Signal-Android-Archive Backup.proto
|
update_proto Signal-Android-App Backup.proto
|
||||||
mv Backup.proto backuppb/Backup.proto
|
mv Backup.proto backuppb/Backup.proto
|
||||||
|
|
||||||
update_proto Signal-Desktop DeviceName.proto
|
update_proto Signal-Desktop DeviceName.proto
|
||||||
# TODO these were moved to libsignal only
|
# TODO this was moved to libsignal only
|
||||||
#update_proto Signal-Desktop UnidentifiedDelivery.proto
|
#update_proto Signal-Desktop UnidentifiedDelivery.proto
|
||||||
#update_proto Signal-Desktop ContactDiscovery.proto
|
# Android has CDSI.proto too, but the types have more generic names (since android uses a different package name)
|
||||||
|
update_proto Signal-Desktop ContactDiscovery.proto
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ package signalmeow
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"crypto/hmac"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
@ -165,19 +166,24 @@ func PerformProvisioning(ctx context.Context, deviceStore store.DeviceStore, dev
|
||||||
DeviceID: deviceId,
|
DeviceID: deviceId,
|
||||||
Number: *provisioningMessage.Number,
|
Number: *provisioningMessage.Number,
|
||||||
Password: password,
|
Password: password,
|
||||||
|
MasterKey: provisioningMessage.GetMasterKey(),
|
||||||
AccountEntropyPool: libsignalgo.AccountEntropyPool(provisioningMessage.GetAccountEntropyPool()),
|
AccountEntropyPool: libsignalgo.AccountEntropyPool(provisioningMessage.GetAccountEntropyPool()),
|
||||||
EphemeralBackupKey: libsignalgo.BytesToBackupKey(provisioningMessage.GetEphemeralBackupKey()),
|
EphemeralBackupKey: libsignalgo.BytesToBackupKey(provisioningMessage.GetEphemeralBackupKey()),
|
||||||
MediaRootBackupKey: libsignalgo.BytesToBackupKey(provisioningMessage.GetMediaRootBackupKey()),
|
MediaRootBackupKey: libsignalgo.BytesToBackupKey(provisioningMessage.GetMediaRootBackupKey()),
|
||||||
}
|
}
|
||||||
if provisioningMessage.GetAccountEntropyPool() != "" {
|
if provisioningMessage.GetAccountEntropyPool() != "" {
|
||||||
data.MasterKey, err = libsignalgo.AccountEntropyPool(provisioningMessage.GetAccountEntropyPool()).DeriveSVRKey()
|
var masterKey []byte
|
||||||
|
masterKey, err = libsignalgo.AccountEntropyPool(provisioningMessage.GetAccountEntropyPool()).DeriveSVRKey()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Err(err).Msg("Failed to derive master key from account entropy pool")
|
log.Err(err).Msg("Failed to derive master key from account entropy pool")
|
||||||
} else {
|
} else {
|
||||||
log.Debug().Msg("Derived master key from account entropy pool")
|
log.Debug().Msg("Derived master key from account entropy pool")
|
||||||
}
|
}
|
||||||
} else {
|
if data.MasterKey == nil {
|
||||||
log.Warn().Msg("No account entropy pool in provisioning message")
|
data.MasterKey = masterKey
|
||||||
|
} else if !hmac.Equal(data.MasterKey, masterKey) {
|
||||||
|
log.Warn().Msg("Master key mismatch")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store the provisioning data
|
// Store the provisioning data
|
||||||
|
|
|
||||||
|
|
@ -357,7 +357,7 @@ func (cli *Client) incomingAPIMessageHandler(ctx context.Context, req *signalpb.
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
log = log.With().
|
log = log.With().
|
||||||
Uint64("envelope_timestamp", envelope.GetClientTimestamp()).
|
Uint64("envelope_timestamp", envelope.GetTimestamp()).
|
||||||
Uint64("server_timestamp", envelope.GetServerTimestamp()).
|
Uint64("server_timestamp", envelope.GetServerTimestamp()).
|
||||||
Logger()
|
Logger()
|
||||||
ctx = log.WithContext(ctx)
|
ctx = log.WithContext(ctx)
|
||||||
|
|
@ -368,7 +368,7 @@ func (cli *Client) incomingAPIMessageHandler(ctx context.Context, req *signalpb.
|
||||||
Str("source_service_id", envelope.GetSourceServiceId()).
|
Str("source_service_id", envelope.GetSourceServiceId()).
|
||||||
Hex("destination_service_id_bytes", envelope.GetDestinationServiceIdBinary()).
|
Hex("destination_service_id_bytes", envelope.GetDestinationServiceIdBinary()).
|
||||||
Hex("source_service_id_bytes", envelope.GetSourceServiceIdBinary()).
|
Hex("source_service_id_bytes", envelope.GetSourceServiceIdBinary()).
|
||||||
Uint32("source_device_id", envelope.GetSourceDeviceId()).
|
Uint32("source_device_id", envelope.GetSourceDevice()).
|
||||||
Object("parsed_destination_service_id", destinationServiceID).
|
Object("parsed_destination_service_id", destinationServiceID).
|
||||||
Object("parsed_source_service_id", sourceServiceID).
|
Object("parsed_source_service_id", sourceServiceID).
|
||||||
Int32("envelope_type_id", int32(envelope.GetType())).
|
Int32("envelope_type_id", int32(envelope.GetType())).
|
||||||
|
|
@ -436,20 +436,20 @@ func (cli *Client) handleDecryptedResult(
|
||||||
Bool("urgent", envelope.GetUrgent()).
|
Bool("urgent", envelope.GetUrgent()).
|
||||||
Stringer("content_hint", result.ContentHint).
|
Stringer("content_hint", result.ContentHint).
|
||||||
Uint64("server_ts", envelope.GetServerTimestamp()).
|
Uint64("server_ts", envelope.GetServerTimestamp()).
|
||||||
Uint64("client_ts", envelope.GetClientTimestamp()).
|
Uint64("client_ts", envelope.GetTimestamp()).
|
||||||
Msg("No sender address received")
|
Msg("No sender address received")
|
||||||
return nil
|
return nil
|
||||||
} else if theirServiceID, err = result.SenderAddress.NameServiceID(); err != nil {
|
} else if theirServiceID, err = result.SenderAddress.NameServiceID(); err != nil {
|
||||||
log.Warn().
|
log.Warn().
|
||||||
Uint64("server_ts", envelope.GetServerTimestamp()).
|
Uint64("server_ts", envelope.GetServerTimestamp()).
|
||||||
Uint64("client_ts", envelope.GetClientTimestamp()).
|
Uint64("client_ts", envelope.GetTimestamp()).
|
||||||
Msg("Failed to get sender name as service ID")
|
Msg("Failed to get sender name as service ID")
|
||||||
return fmt.Errorf("failed to get sender name as service ID: %w", err)
|
return fmt.Errorf("failed to get sender name as service ID: %w", err)
|
||||||
} else if theirServiceID.Type != libsignalgo.ServiceIDTypeACI {
|
} else if theirServiceID.Type != libsignalgo.ServiceIDTypeACI {
|
||||||
log.Warn().
|
log.Warn().
|
||||||
Any("their_service_id", theirServiceID).
|
Any("their_service_id", theirServiceID).
|
||||||
Uint64("server_ts", envelope.GetServerTimestamp()).
|
Uint64("server_ts", envelope.GetServerTimestamp()).
|
||||||
Uint64("client_ts", envelope.GetClientTimestamp()).
|
Uint64("client_ts", envelope.GetTimestamp()).
|
||||||
Msg("Dropping message from non-ACI sender")
|
Msg("Dropping message from non-ACI sender")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -469,7 +469,7 @@ func (cli *Client) handleDecryptedResult(
|
||||||
Bool("urgent", envelope.GetUrgent()).
|
Bool("urgent", envelope.GetUrgent()).
|
||||||
Stringer("content_hint", result.ContentHint).
|
Stringer("content_hint", result.ContentHint).
|
||||||
Uint64("server_ts", envelope.GetServerTimestamp()).
|
Uint64("server_ts", envelope.GetServerTimestamp()).
|
||||||
Uint64("client_ts", envelope.GetClientTimestamp()).
|
Uint64("client_ts", envelope.GetTimestamp()).
|
||||||
Stringer("sender", theirServiceID).
|
Stringer("sender", theirServiceID).
|
||||||
Msg("Ignoring already processed event")
|
Msg("Ignoring already processed event")
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -478,7 +478,7 @@ func (cli *Client) handleDecryptedResult(
|
||||||
Bool("urgent", envelope.GetUrgent()).
|
Bool("urgent", envelope.GetUrgent()).
|
||||||
Stringer("content_hint", result.ContentHint).
|
Stringer("content_hint", result.ContentHint).
|
||||||
Uint64("server_ts", envelope.GetServerTimestamp()).
|
Uint64("server_ts", envelope.GetServerTimestamp()).
|
||||||
Uint64("client_ts", envelope.GetClientTimestamp()).
|
Uint64("client_ts", envelope.GetTimestamp()).
|
||||||
Stringer("sender", theirServiceID).
|
Stringer("sender", theirServiceID).
|
||||||
Msg("Decryption error with known sender")
|
Msg("Decryption error with known sender")
|
||||||
// Only send decryption error event if the message was urgent,
|
// Only send decryption error event if the message was urgent,
|
||||||
|
|
@ -489,12 +489,12 @@ func (cli *Client) handleDecryptedResult(
|
||||||
handlerSuccess = cli.handleEvent(&events.DecryptionError{
|
handlerSuccess = cli.handleEvent(&events.DecryptionError{
|
||||||
Sender: theirServiceID.UUID,
|
Sender: theirServiceID.UUID,
|
||||||
Err: result.Err,
|
Err: result.Err,
|
||||||
Timestamp: envelope.GetClientTimestamp(),
|
Timestamp: envelope.GetTimestamp(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if result.Retriable {
|
if result.Retriable {
|
||||||
go func() {
|
go func() {
|
||||||
err := cli.sendRetryRequest(ctx, result, envelope.GetClientTimestamp())
|
err := cli.sendRetryRequest(ctx, result, envelope.GetTimestamp())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Err(err).Msg("Failed to send retry request in background")
|
log.Err(err).Msg("Failed to send retry request in background")
|
||||||
}
|
}
|
||||||
|
|
@ -506,15 +506,15 @@ func (cli *Client) handleDecryptedResult(
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
rawContent := result.Content
|
content := result.Content
|
||||||
if rawContent == nil {
|
if content == nil {
|
||||||
log.Warn().Msg("Decrypted content is nil")
|
log.Warn().Msg("Decrypted content is nil")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
deviceID, _ := result.SenderAddress.DeviceID()
|
deviceID, _ := result.SenderAddress.DeviceID()
|
||||||
log.Trace().
|
log.Trace().
|
||||||
Any("raw_data", rawContent).
|
Any("raw_data", content).
|
||||||
Stringer("sender", theirServiceID).
|
Stringer("sender", theirServiceID).
|
||||||
Uint("sender_device", deviceID).
|
Uint("sender_device", deviceID).
|
||||||
Msg("Raw event data")
|
Msg("Raw event data")
|
||||||
|
|
@ -531,10 +531,9 @@ func (cli *Client) handleDecryptedResult(
|
||||||
}
|
}
|
||||||
logEvt.Bool("unencrypted", result.Unencrypted).Msg("Decrypted message")
|
logEvt.Bool("unencrypted", result.Unencrypted).Msg("Decrypted message")
|
||||||
|
|
||||||
// Handle unencrypted types early and refuse any other unencrypted message
|
if content.DecryptionErrorMessage != nil {
|
||||||
if rawContent.GetDecryptionErrorMessage() != nil {
|
|
||||||
handlerSuccess = true
|
handlerSuccess = true
|
||||||
dem, err := libsignalgo.DeserializeDecryptionErrorMessage(rawContent.GetDecryptionErrorMessage())
|
dem, err := libsignalgo.DeserializeDecryptionErrorMessage(content.DecryptionErrorMessage)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warn().Err(err).Msg("Failed to unmarshal decryption error message")
|
log.Warn().Err(err).Msg("Failed to unmarshal decryption error message")
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -552,9 +551,9 @@ func (cli *Client) handleDecryptedResult(
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there's a sender key distribution message, process it
|
// If there's a sender key distribution message, process it
|
||||||
if rawContent.SenderKeyDistributionMessage != nil {
|
if content.GetSenderKeyDistributionMessage() != nil {
|
||||||
log.Debug().Msg("content includes sender key distribution message")
|
log.Debug().Msg("content includes sender key distribution message")
|
||||||
skdm, err := libsignalgo.DeserializeSenderKeyDistributionMessage(rawContent.SenderKeyDistributionMessage)
|
skdm, err := libsignalgo.DeserializeSenderKeyDistributionMessage(content.GetSenderKeyDistributionMessage())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Err(err).Msg("DeserializeSenderKeyDistributionMessage error")
|
log.Err(err).Msg("DeserializeSenderKeyDistributionMessage error")
|
||||||
return err
|
return err
|
||||||
|
|
@ -571,7 +570,6 @@ func (cli *Client) handleDecryptedResult(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we're getting a message to our PNI, mark it as needing a PNI signature message on the next send
|
|
||||||
if destinationServiceID == cli.Store.PNIServiceID() {
|
if destinationServiceID == cli.Store.PNIServiceID() {
|
||||||
_, err = cli.Store.RecipientStore.LoadAndUpdateRecipient(ctx, theirServiceID.UUID, uuid.Nil, func(recipient *types.Recipient) (changed bool, err error) {
|
_, err = cli.Store.RecipientStore.LoadAndUpdateRecipient(ctx, theirServiceID.UUID, uuid.Nil, func(recipient *types.Recipient) (changed bool, err error) {
|
||||||
if recipient.Whitelisted == nil {
|
if recipient.Whitelisted == nil {
|
||||||
|
|
@ -591,57 +589,50 @@ func (cli *Client) handleDecryptedResult(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we receive a PNI signature message (because we sent to a PNI earlier), process it
|
if content.PniSignatureMessage != nil {
|
||||||
if rawContent.PniSignatureMessage != nil {
|
|
||||||
log.Debug().Msg("Content includes PNI signature message")
|
log.Debug().Msg("Content includes PNI signature message")
|
||||||
err = cli.handlePNISignatureMessage(ctx, theirServiceID, rawContent.PniSignatureMessage)
|
err = cli.handlePNISignatureMessage(ctx, theirServiceID, content.PniSignatureMessage)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Err(err).
|
log.Err(err).
|
||||||
Hex("pni_raw", rawContent.PniSignatureMessage.GetPni()).
|
Hex("pni_raw", content.PniSignatureMessage.GetPni()).
|
||||||
Stringer("aci", theirServiceID.UUID).
|
Stringer("aci", theirServiceID.UUID).
|
||||||
Msg("Failed to verify ACI-PNI mapping")
|
Msg("Failed to verify ACI-PNI mapping")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if content.SyncMessage != nil && theirServiceID == cli.Store.ACIServiceID() {
|
||||||
|
handlerSuccess = cli.handleSyncMessage(ctx, content.SyncMessage, envelope)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
isBlocked, err := cli.Store.RecipientStore.IsBlocked(ctx, theirServiceID.UUID)
|
isBlocked, err := cli.Store.RecipientStore.IsBlocked(ctx, theirServiceID.UUID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Err(err).Stringer("sender", theirServiceID).Msg("Failed to check if sender is blocked")
|
log.Err(err).Stringer("sender", theirServiceID).Msg("Failed to check if sender is blocked")
|
||||||
}
|
}
|
||||||
|
|
||||||
var sendDeliveryReceipt bool
|
var sendDeliveryReceipt bool
|
||||||
var deliveryReceiptTS uint64
|
if content.DataMessage != nil {
|
||||||
switch content := rawContent.Content.(type) {
|
|
||||||
case *signalpb.Content_SyncMessage:
|
|
||||||
if theirServiceID == cli.Store.ACIServiceID() {
|
|
||||||
handlerSuccess = cli.handleSyncMessage(ctx, content.SyncMessage, envelope)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
case *signalpb.Content_DataMessage:
|
|
||||||
handlerSuccess, sendDeliveryReceipt = cli.incomingDataMessage(
|
handlerSuccess, sendDeliveryReceipt = cli.incomingDataMessage(
|
||||||
ctx, content.DataMessage, theirServiceID.UUID, theirServiceID, envelope.GetServerTimestamp(), isBlocked,
|
ctx, content.DataMessage, theirServiceID.UUID, theirServiceID, envelope.GetServerTimestamp(), isBlocked,
|
||||||
)
|
)
|
||||||
deliveryReceiptTS = content.DataMessage.GetTimestamp()
|
} else if content.EditMessage != nil {
|
||||||
case *signalpb.Content_EditMessage:
|
|
||||||
handlerSuccess, sendDeliveryReceipt = cli.incomingEditMessage(
|
handlerSuccess, sendDeliveryReceipt = cli.incomingEditMessage(
|
||||||
ctx, content.EditMessage, theirServiceID.UUID, theirServiceID, envelope.GetServerTimestamp(), isBlocked,
|
ctx, content.EditMessage, theirServiceID.UUID, theirServiceID, envelope.GetServerTimestamp(), isBlocked,
|
||||||
)
|
)
|
||||||
deliveryReceiptTS = content.EditMessage.GetDataMessage().GetTimestamp()
|
|
||||||
case *signalpb.Content_ReceiptMessage:
|
|
||||||
if content.ReceiptMessage.GetType() == signalpb.ReceiptMessage_DELIVERY && theirServiceID == cli.Store.ACIServiceID() {
|
|
||||||
// Ignore delivery receipts from other own devices
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
handlerSuccess = cli.handleEvent(&events.Receipt{
|
if sendDeliveryReceipt && handlerSuccess {
|
||||||
Sender: theirServiceID.UUID,
|
err = cli.sendDeliveryReceipts(ctx, []uint64{content.DataMessage.GetTimestamp()}, theirServiceID.UUID)
|
||||||
Content: content.ReceiptMessage,
|
if err != nil {
|
||||||
})
|
log.Err(err).Msg("sendDeliveryReceipts error")
|
||||||
case *signalpb.Content_TypingMessage:
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if content.TypingMessage != nil && (!isBlocked || content.TypingMessage.GetGroupId() != nil) {
|
||||||
var groupID types.GroupIdentifier
|
var groupID types.GroupIdentifier
|
||||||
if content.TypingMessage.GetGroupId() != nil {
|
if content.TypingMessage.GetGroupId() != nil {
|
||||||
gidBytes := content.TypingMessage.GetGroupId()
|
gidBytes := content.TypingMessage.GetGroupId()
|
||||||
groupID = types.GroupIdentifier(base64.StdEncoding.EncodeToString(gidBytes))
|
groupID = types.GroupIdentifier(base64.StdEncoding.EncodeToString(gidBytes))
|
||||||
}
|
}
|
||||||
if !isBlocked || groupID != "" {
|
|
||||||
// No handler success check here, nobody cares if typing notifications are dropped
|
// No handler success check here, nobody cares if typing notifications are dropped
|
||||||
cli.handleEvent(&events.ChatEvent{
|
cli.handleEvent(&events.ChatEvent{
|
||||||
Info: events.MessageInfo{
|
Info: events.MessageInfo{
|
||||||
|
|
@ -652,8 +643,9 @@ func (cli *Client) handleDecryptedResult(
|
||||||
Event: content.TypingMessage,
|
Event: content.TypingMessage,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
case *signalpb.Content_CallMessage:
|
|
||||||
if !isBlocked && (content.CallMessage.Offer != nil || content.CallMessage.Hangup != nil) {
|
// DM call message (group call is an opaque callMessage and a groupCallUpdate in a dataMessage)
|
||||||
|
if content.CallMessage != nil && (content.CallMessage.Offer != nil || content.CallMessage.Hangup != nil) && !isBlocked {
|
||||||
handlerSuccess = cli.handleEvent(&events.Call{
|
handlerSuccess = cli.handleEvent(&events.Call{
|
||||||
Info: events.MessageInfo{
|
Info: events.MessageInfo{
|
||||||
Sender: theirServiceID.UUID,
|
Sender: theirServiceID.UUID,
|
||||||
|
|
@ -661,30 +653,22 @@ func (cli *Client) handleDecryptedResult(
|
||||||
ServerTimestamp: envelope.GetServerTimestamp(),
|
ServerTimestamp: envelope.GetServerTimestamp(),
|
||||||
},
|
},
|
||||||
// CallMessage doesn't have its own timestamp, use one from the envelope
|
// CallMessage doesn't have its own timestamp, use one from the envelope
|
||||||
Timestamp: envelope.GetClientTimestamp(),
|
Timestamp: envelope.GetTimestamp(),
|
||||||
IsRinging: content.CallMessage.Offer != nil,
|
IsRinging: content.CallMessage.Offer != nil,
|
||||||
})
|
}) && handlerSuccess
|
||||||
}
|
|
||||||
case *signalpb.Content_DecryptionErrorMessage:
|
|
||||||
// These should've been handled earlier
|
|
||||||
log.Warn().Msg("Unexpected decryption error message content in decrypted message")
|
|
||||||
case *signalpb.Content_NullMessage:
|
|
||||||
// This is intentionally ignored
|
|
||||||
case *signalpb.Content_StoryMessage:
|
|
||||||
// This is also ignored for now
|
|
||||||
default:
|
|
||||||
if rawContent.PniSignatureMessage == nil && rawContent.SenderKeyDistributionMessage == nil {
|
|
||||||
log.Warn().Type("content_type", content).Msg("Unrecognized message content type")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if sendDeliveryReceipt && handlerSuccess {
|
// Read and delivery receipts
|
||||||
err = cli.sendDeliveryReceipts(ctx, []uint64{deliveryReceiptTS}, theirServiceID.UUID)
|
if content.ReceiptMessage != nil {
|
||||||
if err != nil {
|
if content.GetReceiptMessage().GetType() == signalpb.ReceiptMessage_DELIVERY && theirServiceID == cli.Store.ACIServiceID() {
|
||||||
log.Err(err).Msg("sendDeliveryReceipts error")
|
// Ignore delivery receipts from other own devices
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
handlerSuccess = cli.handleEvent(&events.Receipt{
|
||||||
|
Sender: theirServiceID.UUID,
|
||||||
|
Content: content.ReceiptMessage,
|
||||||
|
}) && handlerSuccess
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -699,9 +683,9 @@ func (cli *Client) handleSyncMessage(ctx context.Context, msg *signalpb.SyncMess
|
||||||
// TODO: handle more sync messages
|
// TODO: handle more sync messages
|
||||||
handlerSuccess = true
|
handlerSuccess = true
|
||||||
log := zerolog.Ctx(ctx)
|
log := zerolog.Ctx(ctx)
|
||||||
switch content := msg.Content.(type) {
|
if msg.Keys != nil {
|
||||||
case *signalpb.SyncMessage_Keys_:
|
aep := libsignalgo.AccountEntropyPool(msg.Keys.GetAccountEntropyPool())
|
||||||
aep := libsignalgo.AccountEntropyPool(content.Keys.GetAccountEntropyPool())
|
cli.Store.MasterKey = msg.Keys.GetMaster()
|
||||||
if aep != "" {
|
if aep != "" {
|
||||||
aepMasterKey, err := aep.DeriveSVRKey()
|
aepMasterKey, err := aep.DeriveSVRKey()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -724,18 +708,11 @@ func (cli *Client) handleSyncMessage(ctx context.Context, msg *signalpb.SyncMess
|
||||||
log.Info().Msg("Received master key")
|
log.Info().Msg("Received master key")
|
||||||
go cli.SyncStorage(ctx)
|
go cli.SyncStorage(ctx)
|
||||||
}
|
}
|
||||||
case *signalpb.SyncMessage_FetchLatest_:
|
} else if msg.GetFetchLatest().GetType() == signalpb.SyncMessage_FetchLatest_STORAGE_MANIFEST {
|
||||||
switch content.FetchLatest.GetType() {
|
|
||||||
case signalpb.SyncMessage_FetchLatest_STORAGE_MANIFEST:
|
|
||||||
log.Debug().Msg("Received storage manifest fetch latest notice")
|
log.Debug().Msg("Received storage manifest fetch latest notice")
|
||||||
go cli.SyncStorage(ctx)
|
go cli.SyncStorage(ctx)
|
||||||
default:
|
|
||||||
log.Debug().
|
|
||||||
Stringer("fetch_latest_type", content.FetchLatest.GetType()).
|
|
||||||
Msg("Received unknown fetch latest notice")
|
|
||||||
}
|
}
|
||||||
case *signalpb.SyncMessage_Sent_:
|
syncSent := msg.GetSent()
|
||||||
syncSent := content.Sent
|
|
||||||
if syncSent.GetMessage() != nil || syncSent.GetEditMessage() != nil {
|
if syncSent.GetMessage() != nil || syncSent.GetEditMessage() != nil {
|
||||||
syncDestinationServiceID, err := ParseStringOrBinaryServiceID(syncSent.GetDestinationServiceId(), syncSent.GetDestinationServiceIdBinary())
|
syncDestinationServiceID, err := ParseStringOrBinaryServiceID(syncSent.GetDestinationServiceId(), syncSent.GetDestinationServiceIdBinary())
|
||||||
if err != nil && !errors.Is(err, ErrEmptyUUIDInput) {
|
if err != nil && !errors.Is(err, ErrEmptyUUIDInput) {
|
||||||
|
|
@ -771,18 +748,19 @@ func (cli *Client) handleSyncMessage(ctx context.Context, msg *signalpb.SyncMess
|
||||||
|
|
||||||
if syncDestinationServiceID.IsEmpty() && syncSent.GetMessage().GetGroupV2() == nil && syncSent.GetEditMessage().GetDataMessage().GetGroupV2() == nil {
|
if syncDestinationServiceID.IsEmpty() && syncSent.GetMessage().GetGroupV2() == nil && syncSent.GetEditMessage().GetDataMessage().GetGroupV2() == nil {
|
||||||
log.Warn().Msg("sync message sent destination is nil")
|
log.Warn().Msg("sync message sent destination is nil")
|
||||||
} else if syncSent.Message != nil {
|
} else if msg.Sent.Message != nil {
|
||||||
// TODO handle expiration start ts, and maybe the sync message ts?
|
// TODO handle expiration start ts, and maybe the sync message ts?
|
||||||
cli.incomingDataMessage(ctx, syncSent.Message, cli.Store.ACI, syncDestinationServiceID, envelope.GetServerTimestamp(), false)
|
cli.incomingDataMessage(ctx, msg.Sent.Message, cli.Store.ACI, syncDestinationServiceID, envelope.GetServerTimestamp(), false)
|
||||||
} else if syncSent.EditMessage != nil {
|
} else if msg.Sent.EditMessage != nil {
|
||||||
cli.incomingEditMessage(ctx, syncSent.EditMessage, cli.Store.ACI, syncDestinationServiceID, envelope.GetServerTimestamp(), false)
|
cli.incomingEditMessage(ctx, msg.Sent.EditMessage, cli.Store.ACI, syncDestinationServiceID, envelope.GetServerTimestamp(), false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case *signalpb.SyncMessage_Contacts_:
|
if msg.Contacts != nil {
|
||||||
log.Debug().Msg("Recieved sync message contacts")
|
log.Debug().Msg("Recieved sync message contacts")
|
||||||
if content.Contacts.Blob != nil {
|
blob := msg.Contacts.Blob
|
||||||
|
if blob != nil {
|
||||||
// TODO roundtrip via disk to save memory
|
// TODO roundtrip via disk to save memory
|
||||||
contactsBytes, err := DownloadAttachmentWithPointer(ctx, content.Contacts.Blob, nil, nil)
|
contactsBytes, err := DownloadAttachmentWithPointer(ctx, blob, nil, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Err(err).Msg("Contacts Sync DownloadAttachment error")
|
log.Err(err).Msg("Contacts Sync DownloadAttachment error")
|
||||||
}
|
}
|
||||||
|
|
@ -795,7 +773,7 @@ func (cli *Client) handleSyncMessage(ctx context.Context, msg *signalpb.SyncMess
|
||||||
convertedContacts := make([]*types.Recipient, 0, len(contacts))
|
convertedContacts := make([]*types.Recipient, 0, len(contacts))
|
||||||
err = cli.Store.DoContactTxn(ctx, func(ctx context.Context) error {
|
err = cli.Store.DoContactTxn(ctx, func(ctx context.Context) error {
|
||||||
for i, signalContact := range contacts {
|
for i, signalContact := range contacts {
|
||||||
if (signalContact.Aci == nil || *signalContact.Aci == "") && len(signalContact.AciBinary) != 16 {
|
if signalContact.Aci == nil || *signalContact.Aci == "" {
|
||||||
// TODO lookup PNI via CDSI and store that when ACI is missing?
|
// TODO lookup PNI via CDSI and store that when ACI is missing?
|
||||||
log.Info().
|
log.Info().
|
||||||
Any("contact", signalContact).
|
Any("contact", signalContact).
|
||||||
|
|
@ -818,14 +796,22 @@ func (cli *Client) handleSyncMessage(ctx context.Context, msg *signalpb.SyncMess
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case *signalpb.SyncMessage_DeleteForMe_:
|
}
|
||||||
handlerSuccess = cli.handleEvent(&events.DeleteForMe{
|
if msg.Read != nil {
|
||||||
Timestamp: envelope.GetClientTimestamp(),
|
handlerSuccess = cli.handleEvent(&events.ReadSelf{
|
||||||
SyncMessage_DeleteForMe: content.DeleteForMe,
|
Timestamp: envelope.GetTimestamp(),
|
||||||
|
Messages: msg.GetRead(),
|
||||||
})
|
})
|
||||||
case *signalpb.SyncMessage_MessageRequestResponse_:
|
}
|
||||||
aciUUID, _ := ParseStringOrBinaryUUID(content.MessageRequestResponse.GetThreadAci(), content.MessageRequestResponse.GetThreadAciBinary())
|
if msg.DeleteForMe != nil {
|
||||||
if aciUUID != uuid.Nil && content.MessageRequestResponse.GetType() == signalpb.SyncMessage_MessageRequestResponse_ACCEPT {
|
handlerSuccess = cli.handleEvent(&events.DeleteForMe{
|
||||||
|
Timestamp: envelope.GetTimestamp(),
|
||||||
|
SyncMessage_DeleteForMe: msg.DeleteForMe,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if msg.MessageRequestResponse != nil {
|
||||||
|
aciUUID, _ := ParseStringOrBinaryUUID(msg.MessageRequestResponse.GetThreadAci(), msg.MessageRequestResponse.GetThreadAciBinary())
|
||||||
|
if aciUUID != uuid.Nil && msg.MessageRequestResponse.GetType() == signalpb.SyncMessage_MessageRequestResponse_ACCEPT {
|
||||||
_, err := cli.Store.RecipientStore.LoadAndUpdateRecipient(ctx, aciUUID, uuid.Nil, func(recipient *types.Recipient) (changed bool, err error) {
|
_, err := cli.Store.RecipientStore.LoadAndUpdateRecipient(ctx, aciUUID, uuid.Nil, func(recipient *types.Recipient) (changed bool, err error) {
|
||||||
changed = !ptr.Val(recipient.Whitelisted) || recipient.NeedsPNISignature
|
changed = !ptr.Val(recipient.Whitelisted) || recipient.NeedsPNISignature
|
||||||
recipient.Whitelisted = ptr.Ptr(true)
|
recipient.Whitelisted = ptr.Ptr(true)
|
||||||
|
|
@ -837,23 +823,16 @@ func (cli *Client) handleSyncMessage(ctx context.Context, msg *signalpb.SyncMess
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var groupID *libsignalgo.GroupIdentifier
|
var groupID *libsignalgo.GroupIdentifier
|
||||||
if len(content.MessageRequestResponse.GroupId) == libsignalgo.GroupIdentifierLength {
|
if len(msg.MessageRequestResponse.GroupId) == libsignalgo.GroupIdentifierLength {
|
||||||
groupID = (*libsignalgo.GroupIdentifier)(content.MessageRequestResponse.GroupId)
|
groupID = (*libsignalgo.GroupIdentifier)(msg.MessageRequestResponse.GroupId)
|
||||||
}
|
}
|
||||||
handlerSuccess = cli.handleEvent(&events.MessageRequestResponse{
|
handlerSuccess = cli.handleEvent(&events.MessageRequestResponse{
|
||||||
Timestamp: envelope.GetClientTimestamp(),
|
Timestamp: envelope.GetTimestamp(),
|
||||||
ThreadACI: aciUUID,
|
ThreadACI: aciUUID,
|
||||||
GroupID: groupID,
|
GroupID: groupID,
|
||||||
Type: content.MessageRequestResponse.GetType(),
|
Type: msg.MessageRequestResponse.GetType(),
|
||||||
Raw: content.MessageRequestResponse,
|
Raw: msg.MessageRequestResponse,
|
||||||
})
|
})
|
||||||
default:
|
|
||||||
if msg.Read != nil {
|
|
||||||
handlerSuccess = cli.handleEvent(&events.ReadSelf{
|
|
||||||
Timestamp: envelope.GetClientTimestamp(),
|
|
||||||
Messages: msg.Read,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -64,14 +64,14 @@ func (cli *Client) decryptEnvelope(
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
|
|
||||||
case signalpb.Envelope_PREKEY_MESSAGE, signalpb.Envelope_DOUBLE_RATCHET:
|
case signalpb.Envelope_PREKEY_BUNDLE, signalpb.Envelope_CIPHERTEXT:
|
||||||
sender, err := sourceServiceID.Address(uint(envelope.GetSourceDeviceId()))
|
sender, err := sourceServiceID.Address(uint(envelope.GetSourceDevice()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return DecryptionResult{Err: fmt.Errorf("failed to wrap address: %v", err)}
|
return DecryptionResult{Err: fmt.Errorf("failed to wrap address: %v", err)}
|
||||||
}
|
}
|
||||||
var result *DecryptionResult
|
var result *DecryptionResult
|
||||||
var bundleType string
|
var bundleType string
|
||||||
if *envelope.Type == signalpb.Envelope_PREKEY_MESSAGE {
|
if *envelope.Type == signalpb.Envelope_PREKEY_BUNDLE {
|
||||||
result, err = cli.prekeyDecrypt(ctx, destinationServiceID, sender, envelope.Content, envelope.GetServerTimestamp())
|
result, err = cli.prekeyDecrypt(ctx, destinationServiceID, sender, envelope.Content, envelope.GetServerTimestamp())
|
||||||
bundleType = "prekey bundle"
|
bundleType = "prekey bundle"
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -90,7 +90,7 @@ func (cli *Client) decryptEnvelope(
|
||||||
return *result
|
return *result
|
||||||
|
|
||||||
case signalpb.Envelope_PLAINTEXT_CONTENT:
|
case signalpb.Envelope_PLAINTEXT_CONTENT:
|
||||||
addr, err := sourceServiceID.Address(uint(envelope.GetSourceDeviceId()))
|
addr, err := sourceServiceID.Address(uint(envelope.GetSourceDevice()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return DecryptionResult{Err: fmt.Errorf("failed to wrap address: %v", err)}
|
return DecryptionResult{Err: fmt.Errorf("failed to wrap address: %v", err)}
|
||||||
}
|
}
|
||||||
|
|
@ -100,13 +100,16 @@ func (cli *Client) decryptEnvelope(
|
||||||
}
|
}
|
||||||
return DecryptionResult{
|
return DecryptionResult{
|
||||||
SenderAddress: addr,
|
SenderAddress: addr,
|
||||||
Content: &signalpb.Content{Content: &signalpb.Content_DecryptionErrorMessage{DecryptionErrorMessage: content}},
|
Content: &signalpb.Content{DecryptionErrorMessage: content},
|
||||||
Unencrypted: true,
|
Unencrypted: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
case signalpb.Envelope_SERVER_DELIVERY_RECEIPT:
|
case signalpb.Envelope_SERVER_DELIVERY_RECEIPT:
|
||||||
return DecryptionResult{Err: fmt.Errorf("server delivery receipt envelopes are not yet supported")}
|
return DecryptionResult{Err: fmt.Errorf("server delivery receipt envelopes are not yet supported")}
|
||||||
|
|
||||||
|
case signalpb.Envelope_SENDERKEY_MESSAGE:
|
||||||
|
return DecryptionResult{Err: fmt.Errorf("senderkey message envelopes are not yet supported")}
|
||||||
|
|
||||||
case signalpb.Envelope_UNKNOWN:
|
case signalpb.Envelope_UNKNOWN:
|
||||||
return DecryptionResult{Err: fmt.Errorf("unknown envelope type")}
|
return DecryptionResult{Err: fmt.Errorf("unknown envelope type")}
|
||||||
|
|
||||||
|
|
@ -185,17 +188,12 @@ func (cli *Client) prekeyDecrypt(
|
||||||
if is == nil {
|
if is == nil {
|
||||||
return nil, fmt.Errorf("no identity store found for %s", destination)
|
return nil, fmt.Errorf("no identity store found for %s", destination)
|
||||||
}
|
}
|
||||||
destinationAddress, err := destination.Address(uint(cli.Store.DeviceID))
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to get own/destination address: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
plaintext, ciphertextHash, err := cli.bufferedDecryptTxn(ctx, encryptedContent, serverTimestamp, func(ctx context.Context) ([]byte, error) {
|
plaintext, ciphertextHash, err := cli.bufferedDecryptTxn(ctx, encryptedContent, serverTimestamp, func(ctx context.Context) ([]byte, error) {
|
||||||
return libsignalgo.DecryptPreKey(
|
return libsignalgo.DecryptPreKey(
|
||||||
ctx,
|
ctx,
|
||||||
preKeyMessage,
|
preKeyMessage,
|
||||||
sender,
|
sender,
|
||||||
destinationAddress,
|
|
||||||
ss,
|
ss,
|
||||||
is,
|
is,
|
||||||
pks,
|
pks,
|
||||||
|
|
@ -243,16 +241,11 @@ func (cli *Client) decryptCiphertextEnvelope(
|
||||||
if identityStore == nil {
|
if identityStore == nil {
|
||||||
return nil, fmt.Errorf("no identity store for destination service ID %s", destinationServiceID)
|
return nil, fmt.Errorf("no identity store for destination service ID %s", destinationServiceID)
|
||||||
}
|
}
|
||||||
destinationAddress, err := destinationServiceID.Address(uint(cli.Store.DeviceID))
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to get own address: %w", err)
|
|
||||||
}
|
|
||||||
plaintext, ciphertextHash, err := cli.bufferedDecryptTxn(ctx, ciphertext, serverTimestamp, func(ctx context.Context) ([]byte, error) {
|
plaintext, ciphertextHash, err := cli.bufferedDecryptTxn(ctx, ciphertext, serverTimestamp, func(ctx context.Context) ([]byte, error) {
|
||||||
return libsignalgo.Decrypt(
|
return libsignalgo.Decrypt(
|
||||||
ctx,
|
ctx,
|
||||||
message,
|
message,
|
||||||
senderAddress,
|
senderAddress,
|
||||||
destinationAddress,
|
|
||||||
sessionStore,
|
sessionStore,
|
||||||
identityStore,
|
identityStore,
|
||||||
)
|
)
|
||||||
|
|
@ -401,9 +394,7 @@ func (cli *Client) decryptUnidentifiedSenderEnvelope(ctx context.Context, destin
|
||||||
}
|
}
|
||||||
result.Unencrypted = true
|
result.Unencrypted = true
|
||||||
result.Content = &signalpb.Content{
|
result.Content = &signalpb.Content{
|
||||||
Content: &signalpb.Content_DecryptionErrorMessage{
|
|
||||||
DecryptionErrorMessage: usmcContents,
|
DecryptionErrorMessage: usmcContents,
|
||||||
},
|
|
||||||
}
|
}
|
||||||
return result, err
|
return result, err
|
||||||
default:
|
default:
|
||||||
|
|
|
||||||
|
|
@ -19,12 +19,10 @@ package signalmeow
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/rand/v2"
|
|
||||||
"slices"
|
"slices"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
"go.mau.fi/util/random"
|
|
||||||
|
|
||||||
"go.mau.fi/mautrix-signal/pkg/libsignalgo"
|
"go.mau.fi/mautrix-signal/pkg/libsignalgo"
|
||||||
signalpb "go.mau.fi/mautrix-signal/pkg/signalmeow/protobuf"
|
signalpb "go.mau.fi/mautrix-signal/pkg/signalmeow/protobuf"
|
||||||
|
|
@ -65,9 +63,7 @@ func (cli *Client) sendRetryRequest(ctx context.Context, result DecryptionResult
|
||||||
return fmt.Errorf("failed to create ciphertext message from plaintext content: %w", err)
|
return fmt.Errorf("failed to create ciphertext message from plaintext content: %w", err)
|
||||||
}
|
}
|
||||||
_, err = cli.sendContent(ctx, serviceID, uint64(time.Now().UnixMilli()), &signalpb.Content{
|
_, err = cli.sendContent(ctx, serviceID, uint64(time.Now().UnixMilli()), &signalpb.Content{
|
||||||
Content: &signalpb.Content_DecryptionErrorMessage{
|
|
||||||
DecryptionErrorMessage: demBytes,
|
DecryptionErrorMessage: demBytes,
|
||||||
},
|
|
||||||
}, 0, true, result.GroupID, ctm)
|
}, 0, true, result.GroupID, ctm)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to send decryption error message: %w", err)
|
return fmt.Errorf("failed to send decryption error message: %w", err)
|
||||||
|
|
@ -186,11 +182,7 @@ func (cli *Client) handleRetryRequest(
|
||||||
Msg("Not responding to decryption error message")
|
Msg("Not responding to decryption error message")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
retryContent.Content = &signalpb.Content_NullMessage{
|
retryContent.NullMessage = &signalpb.NullMessage{}
|
||||||
NullMessage: &signalpb.NullMessage{
|
|
||||||
Padding: random.Bytes(rand.IntN(511) + 1),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
responseTimestamp := uint64(time.Now().UnixMilli())
|
responseTimestamp := uint64(time.Now().UnixMilli())
|
||||||
if cacheHit {
|
if cacheHit {
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,6 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/rand/v2"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
@ -32,7 +31,6 @@ import (
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
"go.mau.fi/util/exfmt"
|
"go.mau.fi/util/exfmt"
|
||||||
"go.mau.fi/util/ptr"
|
"go.mau.fi/util/ptr"
|
||||||
"go.mau.fi/util/random"
|
|
||||||
"google.golang.org/protobuf/proto"
|
"google.golang.org/protobuf/proto"
|
||||||
|
|
||||||
"go.mau.fi/mautrix-signal/pkg/libsignalgo"
|
"go.mau.fi/mautrix-signal/pkg/libsignalgo"
|
||||||
|
|
@ -173,10 +171,6 @@ func (cli *Client) buildMessagesToSend(
|
||||||
} else if len(sessions) == 0 {
|
} else if len(sessions) == 0 {
|
||||||
return nil, fmt.Errorf("no sessions found for recipient %s", recipient.String())
|
return nil, fmt.Errorf("no sessions found for recipient %s", recipient.String())
|
||||||
}
|
}
|
||||||
localAddress, err := cli.Store.ACIServiceID().Address(uint(cli.Store.DeviceID))
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to get own address: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
messages := make([]MyMessage, 0, len(sessions))
|
messages := make([]MyMessage, 0, len(sessions))
|
||||||
for _, tuple := range sessions {
|
for _, tuple := range sessions {
|
||||||
|
|
@ -199,7 +193,7 @@ func (cli *Client) buildMessagesToSend(
|
||||||
|
|
||||||
includeE164 := groupID == nil && cli.Store.AccountRecord.GetPhoneNumberSharingMode() == signalpb.AccountRecord_EVERYBODY
|
includeE164 := groupID == nil && cli.Store.AccountRecord.GetPhoneNumberSharingMode() == signalpb.AccountRecord_EVERYBODY
|
||||||
envelopeType, encryptedPayload, err := cli.buildMessageToSend(
|
envelopeType, encryptedPayload, err := cli.buildMessageToSend(
|
||||||
ctx, tuple.Address, localAddress, paddedMessage, getContentHint(content), ctmOverride, groupID, includeE164, unauthenticated,
|
ctx, tuple.Address, paddedMessage, getContentHint(content), ctmOverride, groupID, includeE164, unauthenticated,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -224,9 +218,11 @@ func (cli *Client) buildMessagesToSend(
|
||||||
func ctmTypeToEnvelopeType(ctmType libsignalgo.CiphertextMessageType) signalpb.Envelope_Type {
|
func ctmTypeToEnvelopeType(ctmType libsignalgo.CiphertextMessageType) signalpb.Envelope_Type {
|
||||||
switch ctmType {
|
switch ctmType {
|
||||||
case libsignalgo.CiphertextMessageTypeWhisper:
|
case libsignalgo.CiphertextMessageTypeWhisper:
|
||||||
return signalpb.Envelope_DOUBLE_RATCHET // 2 -> 1
|
return signalpb.Envelope_CIPHERTEXT // 2 -> 1
|
||||||
case libsignalgo.CiphertextMessageTypePreKey:
|
case libsignalgo.CiphertextMessageTypePreKey:
|
||||||
return signalpb.Envelope_PREKEY_MESSAGE // 3 -> 3
|
return signalpb.Envelope_PREKEY_BUNDLE // 3 -> 3
|
||||||
|
case libsignalgo.CiphertextMessageTypeSenderKey:
|
||||||
|
return signalpb.Envelope_SENDERKEY_MESSAGE // 7 -> 7
|
||||||
case libsignalgo.CiphertextMessageTypePlaintext:
|
case libsignalgo.CiphertextMessageTypePlaintext:
|
||||||
return signalpb.Envelope_PLAINTEXT_CONTENT // 8 -> 8
|
return signalpb.Envelope_PLAINTEXT_CONTENT // 8 -> 8
|
||||||
default:
|
default:
|
||||||
|
|
@ -236,7 +232,7 @@ func ctmTypeToEnvelopeType(ctmType libsignalgo.CiphertextMessageType) signalpb.E
|
||||||
|
|
||||||
func (cli *Client) buildMessageToSend(
|
func (cli *Client) buildMessageToSend(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
recipientAddress, localAddress *libsignalgo.Address,
|
recipientAddress *libsignalgo.Address,
|
||||||
paddedMessage []byte,
|
paddedMessage []byte,
|
||||||
contentHint libsignalgo.UnidentifiedSenderMessageContentHint,
|
contentHint libsignalgo.UnidentifiedSenderMessageContentHint,
|
||||||
ciphertextMessage *libsignalgo.CiphertextMessage,
|
ciphertextMessage *libsignalgo.CiphertextMessage,
|
||||||
|
|
@ -248,7 +244,6 @@ func (cli *Client) buildMessageToSend(
|
||||||
ctx,
|
ctx,
|
||||||
paddedMessage,
|
paddedMessage,
|
||||||
recipientAddress,
|
recipientAddress,
|
||||||
localAddress,
|
|
||||||
cli.Store.ACISessionStore,
|
cli.Store.ACISessionStore,
|
||||||
cli.Store.ACIIdentityStore,
|
cli.Store.ACIIdentityStore,
|
||||||
)
|
)
|
||||||
|
|
@ -302,21 +297,11 @@ type SendResult interface {
|
||||||
func (gmsr *GroupMessageSendResult) isSendResult() {}
|
func (gmsr *GroupMessageSendResult) isSendResult() {}
|
||||||
func (smsr *SendMessageResult) isSendResult() {}
|
func (smsr *SendMessageResult) isSendResult() {}
|
||||||
|
|
||||||
func WrapSyncMessage(content *signalpb.SyncMessage) *signalpb.Content {
|
func contentFromDataMessage(dataMessage *signalpb.DataMessage) *signalpb.Content {
|
||||||
content.Padding = random.Bytes(rand.IntN(511) + 1)
|
|
||||||
return &signalpb.Content{
|
return &signalpb.Content{
|
||||||
Content: &signalpb.Content_SyncMessage{SyncMessage: content},
|
DataMessage: dataMessage,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func syncSentMessage(sent *signalpb.SyncMessage_Sent) *signalpb.Content {
|
|
||||||
return WrapSyncMessage(&signalpb.SyncMessage{
|
|
||||||
Content: &signalpb.SyncMessage_Sent_{
|
|
||||||
Sent: sent,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func syncMessageFromGroupDataMessage(dataMessage *signalpb.DataMessage, results []SuccessfulSendResult) *signalpb.Content {
|
func syncMessageFromGroupDataMessage(dataMessage *signalpb.DataMessage, results []SuccessfulSendResult) *signalpb.Content {
|
||||||
unidentifiedStatuses := []*signalpb.SyncMessage_Sent_UnidentifiedDeliveryStatus{}
|
unidentifiedStatuses := []*signalpb.SyncMessage_Sent_UnidentifiedDeliveryStatus{}
|
||||||
for _, result := range results {
|
for _, result := range results {
|
||||||
|
|
@ -325,14 +310,17 @@ func syncMessageFromGroupDataMessage(dataMessage *signalpb.DataMessage, results
|
||||||
Unidentified: &result.Unidentified,
|
Unidentified: &result.Unidentified,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return syncSentMessage(&signalpb.SyncMessage_Sent{
|
return &signalpb.Content{
|
||||||
|
SyncMessage: &signalpb.SyncMessage{
|
||||||
|
Sent: &signalpb.SyncMessage_Sent{
|
||||||
Message: dataMessage,
|
Message: dataMessage,
|
||||||
Timestamp: dataMessage.Timestamp,
|
Timestamp: dataMessage.Timestamp,
|
||||||
UnidentifiedStatus: unidentifiedStatuses,
|
UnidentifiedStatus: unidentifiedStatuses,
|
||||||
ExpirationStartTimestamp: ptr.Ptr(uint64(time.Now().UnixMilli())),
|
ExpirationStartTimestamp: ptr.Ptr(uint64(time.Now().UnixMilli())),
|
||||||
})
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func syncMessageFromGroupEditMessage(editMessage *signalpb.EditMessage, results []SuccessfulSendResult) *signalpb.Content {
|
func syncMessageFromGroupEditMessage(editMessage *signalpb.EditMessage, results []SuccessfulSendResult) *signalpb.Content {
|
||||||
unidentifiedStatuses := []*signalpb.SyncMessage_Sent_UnidentifiedDeliveryStatus{}
|
unidentifiedStatuses := []*signalpb.SyncMessage_Sent_UnidentifiedDeliveryStatus{}
|
||||||
for _, result := range results {
|
for _, result := range results {
|
||||||
|
|
@ -341,16 +329,22 @@ func syncMessageFromGroupEditMessage(editMessage *signalpb.EditMessage, results
|
||||||
Unidentified: &result.Unidentified,
|
Unidentified: &result.Unidentified,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return syncSentMessage(&signalpb.SyncMessage_Sent{
|
return &signalpb.Content{
|
||||||
|
SyncMessage: &signalpb.SyncMessage{
|
||||||
|
Sent: &signalpb.SyncMessage_Sent{
|
||||||
EditMessage: editMessage,
|
EditMessage: editMessage,
|
||||||
Timestamp: editMessage.GetDataMessage().Timestamp,
|
Timestamp: editMessage.GetDataMessage().Timestamp,
|
||||||
UnidentifiedStatus: unidentifiedStatuses,
|
UnidentifiedStatus: unidentifiedStatuses,
|
||||||
ExpirationStartTimestamp: ptr.Ptr(uint64(time.Now().UnixMilli())),
|
ExpirationStartTimestamp: ptr.Ptr(uint64(time.Now().UnixMilli())),
|
||||||
})
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func syncMessageFromSoloDataMessage(dataMessage *signalpb.DataMessage, result SuccessfulSendResult) *signalpb.Content {
|
func syncMessageFromSoloDataMessage(dataMessage *signalpb.DataMessage, result SuccessfulSendResult) *signalpb.Content {
|
||||||
return syncSentMessage(&signalpb.SyncMessage_Sent{
|
return &signalpb.Content{
|
||||||
|
SyncMessage: &signalpb.SyncMessage{
|
||||||
|
Sent: &signalpb.SyncMessage_Sent{
|
||||||
Message: dataMessage,
|
Message: dataMessage,
|
||||||
DestinationE164: result.RecipientE164,
|
DestinationE164: result.RecipientE164,
|
||||||
DestinationServiceIdBinary: result.Recipient.Bytes(),
|
DestinationServiceIdBinary: result.Recipient.Bytes(),
|
||||||
|
|
@ -363,11 +357,15 @@ func syncMessageFromSoloDataMessage(dataMessage *signalpb.DataMessage, result Su
|
||||||
DestinationPniIdentityKey: result.DestinationPNIIdentityKey.TrySerialize(),
|
DestinationPniIdentityKey: result.DestinationPNIIdentityKey.TrySerialize(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func syncMessageFromSoloEditMessage(editMessage *signalpb.EditMessage, result SuccessfulSendResult) *signalpb.Content {
|
func syncMessageFromSoloEditMessage(editMessage *signalpb.EditMessage, result SuccessfulSendResult) *signalpb.Content {
|
||||||
return syncSentMessage(&signalpb.SyncMessage_Sent{
|
return &signalpb.Content{
|
||||||
|
SyncMessage: &signalpb.SyncMessage{
|
||||||
|
Sent: &signalpb.SyncMessage_Sent{
|
||||||
EditMessage: editMessage,
|
EditMessage: editMessage,
|
||||||
DestinationE164: result.RecipientE164,
|
DestinationE164: result.RecipientE164,
|
||||||
DestinationServiceIdBinary: result.Recipient.Bytes(),
|
DestinationServiceIdBinary: result.Recipient.Bytes(),
|
||||||
|
|
@ -380,11 +378,21 @@ func syncMessageFromSoloEditMessage(editMessage *signalpb.EditMessage, result Su
|
||||||
DestinationPniIdentityKey: result.DestinationPNIIdentityKey.TrySerialize(),
|
DestinationPniIdentityKey: result.DestinationPNIIdentityKey.TrySerialize(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func syncMessageFromReadReceiptMessage(ctx context.Context, receiptMessage *signalpb.ReceiptMessage, messageSender libsignalgo.ServiceID) *signalpb.Content {
|
func syncMessageFromReadReceiptMessage(ctx context.Context, receiptMessage *signalpb.ReceiptMessage, messageSender libsignalgo.ServiceID) *signalpb.Content {
|
||||||
if *receiptMessage.Type != signalpb.ReceiptMessage_READ || messageSender.Type != libsignalgo.ServiceIDTypeACI {
|
if *receiptMessage.Type != signalpb.ReceiptMessage_READ {
|
||||||
|
zerolog.Ctx(ctx).Warn().
|
||||||
|
Any("receipt_message_type", receiptMessage.Type).
|
||||||
|
Msg("syncMessageFromReadReceiptMessage called with non-read receipt message")
|
||||||
|
return nil
|
||||||
|
} else if messageSender.Type != libsignalgo.ServiceIDTypeACI {
|
||||||
|
zerolog.Ctx(ctx).Warn().
|
||||||
|
Stringer("message_sender", messageSender).
|
||||||
|
Msg("syncMessageFromReadReceiptMessage called with non-ACI message sender")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
read := []*signalpb.SyncMessage_Read{}
|
read := []*signalpb.SyncMessage_Read{}
|
||||||
|
|
@ -394,9 +402,11 @@ func syncMessageFromReadReceiptMessage(ctx context.Context, receiptMessage *sign
|
||||||
SenderAci: proto.String(messageSender.UUID.String()),
|
SenderAci: proto.String(messageSender.UUID.String()),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return WrapSyncMessage(&signalpb.SyncMessage{
|
return &signalpb.Content{
|
||||||
|
SyncMessage: &signalpb.SyncMessage{
|
||||||
Read: read,
|
Read: read,
|
||||||
})
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cli *Client) SendContactSyncRequest(ctx context.Context) error {
|
func (cli *Client) SendContactSyncRequest(ctx context.Context) error {
|
||||||
|
|
@ -412,13 +422,13 @@ func (cli *Client) SendContactSyncRequest(ctx context.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
cli.LastContactRequestTime = time.Now()
|
cli.LastContactRequestTime = time.Now()
|
||||||
_, err := cli.sendContent(ctx, cli.Store.ACIServiceID(), uint64(time.Now().UnixMilli()), WrapSyncMessage(&signalpb.SyncMessage{
|
_, err := cli.sendContent(ctx, cli.Store.ACIServiceID(), uint64(time.Now().UnixMilli()), &signalpb.Content{
|
||||||
Content: &signalpb.SyncMessage_Request_{
|
SyncMessage: &signalpb.SyncMessage{
|
||||||
Request: &signalpb.SyncMessage_Request{
|
Request: &signalpb.SyncMessage_Request{
|
||||||
Type: signalpb.SyncMessage_Request_CONTACTS.Enum(),
|
Type: signalpb.SyncMessage_Request_CONTACTS.Enum(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}), 0, false, nil, nil)
|
}, 0, false, nil, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Err(err).Msg("Failed to send contact sync request message to myself")
|
log.Err(err).Msg("Failed to send contact sync request message to myself")
|
||||||
return err
|
return err
|
||||||
|
|
@ -432,13 +442,13 @@ func (cli *Client) SendStorageMasterKeyRequest(ctx context.Context) error {
|
||||||
Logger()
|
Logger()
|
||||||
ctx = log.WithContext(ctx)
|
ctx = log.WithContext(ctx)
|
||||||
|
|
||||||
_, err := cli.sendContent(ctx, cli.Store.ACIServiceID(), uint64(time.Now().UnixMilli()), WrapSyncMessage(&signalpb.SyncMessage{
|
_, err := cli.sendContent(ctx, cli.Store.ACIServiceID(), uint64(time.Now().UnixMilli()), &signalpb.Content{
|
||||||
Content: &signalpb.SyncMessage_Request_{
|
SyncMessage: &signalpb.SyncMessage{
|
||||||
Request: &signalpb.SyncMessage_Request{
|
Request: &signalpb.SyncMessage_Request{
|
||||||
Type: signalpb.SyncMessage_Request_KEYS.Enum(),
|
Type: signalpb.SyncMessage_Request_KEYS.Enum(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}), 0, false, nil, nil)
|
}, 0, false, nil, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Err(err).Msg("Failed to send key sync request message to myself")
|
log.Err(err).Msg("Failed to send key sync request message to myself")
|
||||||
return err
|
return err
|
||||||
|
|
@ -458,47 +468,38 @@ func TypingMessage(isTyping bool) *signalpb.Content {
|
||||||
} else {
|
} else {
|
||||||
action = signalpb.TypingMessage_STOPPED
|
action = signalpb.TypingMessage_STOPPED
|
||||||
}
|
}
|
||||||
return &signalpb.Content{
|
tm := &signalpb.TypingMessage{
|
||||||
Content: &signalpb.Content_TypingMessage{
|
|
||||||
TypingMessage: &signalpb.TypingMessage{
|
|
||||||
Timestamp: ×tamp,
|
Timestamp: ×tamp,
|
||||||
Action: &action,
|
Action: &action,
|
||||||
},
|
}
|
||||||
},
|
return &signalpb.Content{
|
||||||
|
TypingMessage: tm,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func DeliveredReceiptMessageForTimestamps(timestamps []uint64) *signalpb.Content {
|
func DeliveredReceiptMessageForTimestamps(timestamps []uint64) *signalpb.Content {
|
||||||
return &signalpb.Content{
|
rm := &signalpb.ReceiptMessage{
|
||||||
Content: &signalpb.Content_ReceiptMessage{
|
|
||||||
ReceiptMessage: &signalpb.ReceiptMessage{
|
|
||||||
Timestamp: timestamps,
|
Timestamp: timestamps,
|
||||||
Type: signalpb.ReceiptMessage_DELIVERY.Enum(),
|
Type: signalpb.ReceiptMessage_DELIVERY.Enum(),
|
||||||
},
|
}
|
||||||
},
|
return &signalpb.Content{
|
||||||
|
ReceiptMessage: rm,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func ReadReceptMessageForTimestamps(timestamps []uint64) *signalpb.Content {
|
func ReadReceptMessageForTimestamps(timestamps []uint64) *signalpb.Content {
|
||||||
return &signalpb.Content{
|
rm := &signalpb.ReceiptMessage{
|
||||||
Content: &signalpb.Content_ReceiptMessage{
|
|
||||||
ReceiptMessage: &signalpb.ReceiptMessage{
|
|
||||||
Timestamp: timestamps,
|
Timestamp: timestamps,
|
||||||
Type: signalpb.ReceiptMessage_READ.Enum(),
|
Type: signalpb.ReceiptMessage_READ.Enum(),
|
||||||
},
|
}
|
||||||
},
|
return &signalpb.Content{
|
||||||
|
ReceiptMessage: rm,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func WrapDataMessage(dm *signalpb.DataMessage) *signalpb.Content {
|
func wrapDataMessageInContent(dm *signalpb.DataMessage) *signalpb.Content {
|
||||||
return &signalpb.Content{
|
return &signalpb.Content{
|
||||||
Content: &signalpb.Content_DataMessage{DataMessage: dm},
|
DataMessage: dm,
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func WrapEditMessage(dm *signalpb.EditMessage) *signalpb.Content {
|
|
||||||
return &signalpb.Content{
|
|
||||||
Content: &signalpb.Content_EditMessage{EditMessage: dm},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -525,7 +526,7 @@ func (cli *Client) SendGroupUpdate(ctx context.Context, group *Group, groupConte
|
||||||
Timestamp: ×tamp,
|
Timestamp: ×tamp,
|
||||||
GroupV2: groupContext,
|
GroupV2: groupContext,
|
||||||
}
|
}
|
||||||
content := WrapDataMessage(dm)
|
content := wrapDataMessageInContent(dm)
|
||||||
var recipients []libsignalgo.ServiceID
|
var recipients []libsignalgo.ServiceID
|
||||||
for _, member := range group.Members {
|
for _, member := range group.Members {
|
||||||
serviceID := member.UserServiceID()
|
serviceID := member.UserServiceID()
|
||||||
|
|
@ -563,14 +564,13 @@ func (cli *Client) SendGroupMessage(ctx context.Context, gid types.GroupIdentifi
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
var messageTimestamp uint64
|
var messageTimestamp uint64
|
||||||
switch content := content.Content.(type) {
|
if content.GetDataMessage() != nil {
|
||||||
case *signalpb.Content_DataMessage:
|
|
||||||
messageTimestamp = content.DataMessage.GetTimestamp()
|
messageTimestamp = content.DataMessage.GetTimestamp()
|
||||||
content.DataMessage.GroupV2 = groupMetadataForDataMessage(*group)
|
content.DataMessage.GroupV2 = groupMetadataForDataMessage(*group)
|
||||||
case *signalpb.Content_EditMessage:
|
} else if content.GetEditMessage().GetDataMessage() != nil {
|
||||||
messageTimestamp = content.EditMessage.DataMessage.GetTimestamp()
|
messageTimestamp = content.EditMessage.DataMessage.GetTimestamp()
|
||||||
content.EditMessage.DataMessage.GroupV2 = groupMetadataForDataMessage(*group)
|
content.EditMessage.DataMessage.GroupV2 = groupMetadataForDataMessage(*group)
|
||||||
case *signalpb.Content_TypingMessage:
|
} else if content.GetTypingMessage() != nil {
|
||||||
messageTimestamp = content.TypingMessage.GetTimestamp()
|
messageTimestamp = content.TypingMessage.GetTimestamp()
|
||||||
groupIDBytes, err := group.GroupIdentifier.Bytes()
|
groupIDBytes, err := group.GroupIdentifier.Bytes()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -606,7 +606,7 @@ func (cli *Client) sendToGroup(
|
||||||
FailedToSendTo: []FailedSendResult{},
|
FailedToSendTo: []FailedSendResult{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if content.GetTypingMessage() != nil {
|
if content.TypingMessage != nil {
|
||||||
// Never send typing messages via fallback path
|
// Never send typing messages via fallback path
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
@ -648,16 +648,15 @@ func (cli *Client) sendToGroup(
|
||||||
|
|
||||||
func (cli *Client) sendGroupSyncCopy(
|
func (cli *Client) sendGroupSyncCopy(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
rawContent *signalpb.Content,
|
content *signalpb.Content,
|
||||||
messageTimestamp uint64,
|
messageTimestamp uint64,
|
||||||
result *GroupMessageSendResult,
|
result *GroupMessageSendResult,
|
||||||
groupID *libsignalgo.GroupIdentifier,
|
groupID *libsignalgo.GroupIdentifier,
|
||||||
) {
|
) {
|
||||||
var syncContent *signalpb.Content
|
var syncContent *signalpb.Content
|
||||||
switch content := rawContent.Content.(type) {
|
if content.GetDataMessage() != nil {
|
||||||
case *signalpb.Content_DataMessage:
|
|
||||||
syncContent = syncMessageFromGroupDataMessage(content.DataMessage, result.SuccessfullySentTo)
|
syncContent = syncMessageFromGroupDataMessage(content.DataMessage, result.SuccessfullySentTo)
|
||||||
case *signalpb.Content_EditMessage:
|
} else if content.GetEditMessage() != nil {
|
||||||
syncContent = syncMessageFromGroupEditMessage(content.EditMessage, result.SuccessfullySentTo)
|
syncContent = syncMessageFromGroupEditMessage(content.EditMessage, result.SuccessfullySentTo)
|
||||||
}
|
}
|
||||||
if syncContent != nil {
|
if syncContent != nil {
|
||||||
|
|
@ -668,17 +667,16 @@ func (cli *Client) sendGroupSyncCopy(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cli *Client) sendSyncCopy(ctx context.Context, rawContent *signalpb.Content, messageTS uint64, result *SuccessfulSendResult) bool {
|
func (cli *Client) sendSyncCopy(ctx context.Context, content *signalpb.Content, messageTS uint64, result *SuccessfulSendResult) bool {
|
||||||
var syncContent *signalpb.Content
|
var syncContent *signalpb.Content
|
||||||
switch content := rawContent.Content.(type) {
|
if content.GetDataMessage() != nil {
|
||||||
case *signalpb.Content_DataMessage:
|
|
||||||
syncContent = syncMessageFromSoloDataMessage(content.DataMessage, *result)
|
syncContent = syncMessageFromSoloDataMessage(content.DataMessage, *result)
|
||||||
case *signalpb.Content_EditMessage:
|
} else if content.GetEditMessage() != nil {
|
||||||
syncContent = syncMessageFromSoloEditMessage(content.EditMessage, *result)
|
syncContent = syncMessageFromSoloEditMessage(content.EditMessage, *result)
|
||||||
case *signalpb.Content_ReceiptMessage:
|
} else if content.GetReceiptMessage().GetType() == signalpb.ReceiptMessage_READ {
|
||||||
syncContent = syncMessageFromReadReceiptMessage(ctx, content.ReceiptMessage, result.Recipient)
|
syncContent = syncMessageFromReadReceiptMessage(ctx, content.ReceiptMessage, result.Recipient)
|
||||||
case *signalpb.Content_SyncMessage:
|
} else if content.GetSyncMessage() != nil {
|
||||||
syncContent = rawContent
|
syncContent = content
|
||||||
}
|
}
|
||||||
if syncContent != nil {
|
if syncContent != nil {
|
||||||
_, selfSendErr := cli.sendContent(ctx, cli.Store.ACIServiceID(), messageTS, syncContent, 0, true, nil, nil)
|
_, selfSendErr := cli.sendContent(ctx, cli.Store.ACIServiceID(), messageTS, syncContent, 0, true, nil, nil)
|
||||||
|
|
@ -694,33 +692,30 @@ func (cli *Client) sendSyncCopy(ctx context.Context, rawContent *signalpb.Conten
|
||||||
func (cli *Client) SendMessage(ctx context.Context, recipientID libsignalgo.ServiceID, content *signalpb.Content) SendMessageResult {
|
func (cli *Client) SendMessage(ctx context.Context, recipientID libsignalgo.ServiceID, content *signalpb.Content) SendMessageResult {
|
||||||
// Assemble the content to send
|
// Assemble the content to send
|
||||||
var messageTimestamp uint64
|
var messageTimestamp uint64
|
||||||
switch realContent := content.Content.(type) {
|
switch {
|
||||||
case *signalpb.Content_DataMessage:
|
case content.DataMessage != nil:
|
||||||
messageTimestamp = *realContent.DataMessage.Timestamp
|
messageTimestamp = *content.DataMessage.Timestamp
|
||||||
case *signalpb.Content_EditMessage:
|
case content.EditMessage != nil:
|
||||||
messageTimestamp = *realContent.EditMessage.DataMessage.Timestamp
|
messageTimestamp = *content.EditMessage.DataMessage.Timestamp
|
||||||
case *signalpb.Content_TypingMessage:
|
case content.TypingMessage != nil:
|
||||||
messageTimestamp = *realContent.TypingMessage.Timestamp
|
messageTimestamp = *content.TypingMessage.Timestamp
|
||||||
case *signalpb.Content_SyncMessage,
|
case content.SyncMessage != nil,
|
||||||
*signalpb.Content_NullMessage,
|
content.NullMessage != nil,
|
||||||
*signalpb.Content_ReceiptMessage,
|
content.ReceiptMessage != nil,
|
||||||
*signalpb.Content_DecryptionErrorMessage:
|
content.PniSignatureMessage != nil,
|
||||||
|
content.SenderKeyDistributionMessage != nil,
|
||||||
|
content.DecryptionErrorMessage != nil:
|
||||||
messageTimestamp = currentMessageTimestamp()
|
messageTimestamp = currentMessageTimestamp()
|
||||||
case *signalpb.Content_StoryMessage:
|
|
||||||
// not yet supported
|
|
||||||
default:
|
default:
|
||||||
if content.SenderKeyDistributionMessage == nil && content.PniSignatureMessage == nil {
|
|
||||||
panic(fmt.Errorf("unsupported payload in SendMessage"))
|
panic(fmt.Errorf("unsupported payload in SendMessage"))
|
||||||
}
|
}
|
||||||
messageTimestamp = currentMessageTimestamp()
|
|
||||||
}
|
|
||||||
var aci, pni uuid.UUID
|
var aci, pni uuid.UUID
|
||||||
if recipientID.Type == libsignalgo.ServiceIDTypeACI {
|
if recipientID.Type == libsignalgo.ServiceIDTypeACI {
|
||||||
aci = recipientID.UUID
|
aci = recipientID.UUID
|
||||||
} else if recipientID.Type == libsignalgo.ServiceIDTypePNI {
|
} else if recipientID.Type == libsignalgo.ServiceIDTypePNI {
|
||||||
pni = recipientID.UUID
|
pni = recipientID.UUID
|
||||||
}
|
}
|
||||||
isTypingOrReceipt := content.GetTypingMessage() != nil || content.GetReceiptMessage() != nil
|
isTypingOrReceipt := content.TypingMessage != nil || content.ReceiptMessage != nil
|
||||||
recipientData, err := cli.Store.RecipientStore.LoadAndUpdateRecipient(ctx, aci, pni, func(recipientData *types.Recipient) (changed bool, err error) {
|
recipientData, err := cli.Store.RecipientStore.LoadAndUpdateRecipient(ctx, aci, pni, func(recipientData *types.Recipient) (changed bool, err error) {
|
||||||
if content.GetDataMessage().GetFlags() == uint32(signalpb.DataMessage_PROFILE_KEY_UPDATE) {
|
if content.GetDataMessage().GetFlags() == uint32(signalpb.DataMessage_PROFILE_KEY_UPDATE) {
|
||||||
recipientData.Whitelisted = ptr.Ptr(true)
|
recipientData.Whitelisted = ptr.Ptr(true)
|
||||||
|
|
@ -758,7 +753,7 @@ func (cli *Client) SendMessage(ctx context.Context, recipientID libsignalgo.Serv
|
||||||
cli.sendSyncCopy(ctx, content, messageTimestamp, &res)
|
cli.sendSyncCopy(ctx, content, messageTimestamp, &res)
|
||||||
}
|
}
|
||||||
return SendMessageResult{WasSuccessful: true, SuccessfulSendResult: res}
|
return SendMessageResult{WasSuccessful: true, SuccessfulSendResult: res}
|
||||||
} else if content.GetTypingMessage() != nil && cli.Store.DeviceData.AccountRecord != nil && !cli.Store.DeviceData.AccountRecord.GetTypingIndicators() {
|
} else if content.TypingMessage != nil && cli.Store.DeviceData.AccountRecord != nil && !cli.Store.DeviceData.AccountRecord.GetTypingIndicators() {
|
||||||
zerolog.Ctx(ctx).Debug().Msg("Not sending typing message as typing indicators are disabled")
|
zerolog.Ctx(ctx).Debug().Msg("Not sending typing message as typing indicators are disabled")
|
||||||
res := SuccessfulSendResult{Recipient: recipientID}
|
res := SuccessfulSendResult{Recipient: recipientID}
|
||||||
return SendMessageResult{WasSuccessful: true, SuccessfulSendResult: res}
|
return SendMessageResult{WasSuccessful: true, SuccessfulSendResult: res}
|
||||||
|
|
@ -770,7 +765,7 @@ func (cli *Client) SendMessage(ctx context.Context, recipientID libsignalgo.Serv
|
||||||
return SendMessageResult{WasSuccessful: true, SuccessfulSendResult: res}
|
return SendMessageResult{WasSuccessful: true, SuccessfulSendResult: res}
|
||||||
}
|
}
|
||||||
|
|
||||||
isDeliveryReceipt := content.GetReceiptMessage() != nil && content.GetReceiptMessage().GetType() == signalpb.ReceiptMessage_DELIVERY
|
isDeliveryReceipt := content.ReceiptMessage != nil && content.GetReceiptMessage().GetType() == signalpb.ReceiptMessage_DELIVERY
|
||||||
if recipientID == cli.Store.ACIServiceID() && !isDeliveryReceipt {
|
if recipientID == cli.Store.ACIServiceID() && !isDeliveryReceipt {
|
||||||
res := SuccessfulSendResult{
|
res := SuccessfulSendResult{
|
||||||
Recipient: recipientID,
|
Recipient: recipientID,
|
||||||
|
|
@ -824,38 +819,25 @@ func currentMessageTimestamp() uint64 {
|
||||||
}
|
}
|
||||||
|
|
||||||
func isSyncMessageUrgent(content *signalpb.SyncMessage) bool {
|
func isSyncMessageUrgent(content *signalpb.SyncMessage) bool {
|
||||||
switch content.Content.(type) {
|
return content.Sent != nil || content.Request != nil
|
||||||
case *signalpb.SyncMessage_Request_,
|
|
||||||
*signalpb.SyncMessage_Sent_:
|
|
||||||
return true
|
|
||||||
default:
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func isUrgent(rawContent *signalpb.Content) bool {
|
func isUrgent(content *signalpb.Content) bool {
|
||||||
switch content := rawContent.Content.(type) {
|
return content.DataMessage != nil ||
|
||||||
case *signalpb.Content_SyncMessage:
|
content.CallMessage != nil ||
|
||||||
return isSyncMessageUrgent(content.SyncMessage)
|
content.StoryMessage != nil ||
|
||||||
case *signalpb.Content_DataMessage,
|
content.EditMessage != nil ||
|
||||||
*signalpb.Content_EditMessage,
|
(content.SyncMessage != nil && isSyncMessageUrgent(content.SyncMessage))
|
||||||
*signalpb.Content_CallMessage,
|
|
||||||
*signalpb.Content_StoryMessage:
|
|
||||||
return true
|
|
||||||
default:
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func getContentHint(rawContent *signalpb.Content) libsignalgo.UnidentifiedSenderMessageContentHint {
|
func getContentHint(content *signalpb.Content) libsignalgo.UnidentifiedSenderMessageContentHint {
|
||||||
switch rawContent.Content.(type) {
|
if content.DataMessage != nil || content.EditMessage != nil {
|
||||||
case *signalpb.Content_DataMessage, *signalpb.Content_EditMessage:
|
|
||||||
return libsignalgo.UnidentifiedSenderMessageContentHintResendable
|
return libsignalgo.UnidentifiedSenderMessageContentHintResendable
|
||||||
case *signalpb.Content_TypingMessage, *signalpb.Content_ReceiptMessage:
|
|
||||||
return libsignalgo.UnidentifiedSenderMessageContentHintImplicit
|
|
||||||
default:
|
|
||||||
return libsignalgo.UnidentifiedSenderMessageContentHintDefault
|
|
||||||
}
|
}
|
||||||
|
if content.TypingMessage != nil || content.ReceiptMessage != nil {
|
||||||
|
return libsignalgo.UnidentifiedSenderMessageContentHintImplicit
|
||||||
|
}
|
||||||
|
return libsignalgo.UnidentifiedSenderMessageContentHintDefault
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cli *Client) sendContent(
|
func (cli *Client) sendContent(
|
||||||
|
|
@ -876,12 +858,12 @@ func (cli *Client) sendContent(
|
||||||
ctx = log.WithContext(ctx)
|
ctx = log.WithContext(ctx)
|
||||||
|
|
||||||
// If it's a data message, add our profile key
|
// If it's a data message, add our profile key
|
||||||
if content.GetDataMessage() != nil && content.GetDataMessage().ProfileKey == nil {
|
if content.DataMessage != nil && content.DataMessage.ProfileKey == nil {
|
||||||
profileKey, err := cli.ProfileKeyForSignalID(ctx, cli.Store.ACI)
|
profileKey, err := cli.ProfileKeyForSignalID(ctx, cli.Store.ACI)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Err(err).Msg("Error getting profile key, not adding to outgoing message")
|
log.Err(err).Msg("Error getting profile key, not adding to outgoing message")
|
||||||
} else {
|
} else {
|
||||||
content.GetDataMessage().ProfileKey = profileKey.Slice()
|
content.DataMessage.ProfileKey = profileKey.Slice()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,251 +0,0 @@
|
||||||
// mautrix-signal - A Matrix-signal puppeting bridge.
|
|
||||||
// Copyright (C) 2026 Tulir Asokan
|
|
||||||
//
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU Affero General Public License as published by
|
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU Affero General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Affero General Public License
|
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
package signalmeow
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"context"
|
|
||||||
"crypto/hkdf"
|
|
||||||
"crypto/sha256"
|
|
||||||
"encoding/hex"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"mime/multipart"
|
|
||||||
"net/http"
|
|
||||||
"net/textproto"
|
|
||||||
"sync"
|
|
||||||
|
|
||||||
"go.mau.fi/util/exerrors"
|
|
||||||
"go.mau.fi/util/random"
|
|
||||||
"golang.org/x/sync/semaphore"
|
|
||||||
"google.golang.org/protobuf/proto"
|
|
||||||
|
|
||||||
signalpb "go.mau.fi/mautrix-signal/pkg/signalmeow/protobuf"
|
|
||||||
"go.mau.fi/mautrix-signal/pkg/signalmeow/web"
|
|
||||||
)
|
|
||||||
|
|
||||||
func DownloadStickerPackManifest(ctx context.Context, packID, packKey []byte) (*signalpb.Pack, error) {
|
|
||||||
if len(packID) != 16 {
|
|
||||||
return nil, fmt.Errorf("invalid pack ID length: %d", len(packID))
|
|
||||||
}
|
|
||||||
resp, err := downloadStickerData(ctx, fmt.Sprintf("/stickers/%x/manifest.proto", packID), packKey)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
var pack signalpb.Pack
|
|
||||||
err = proto.Unmarshal(resp, &pack)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to unmarshal decrypted manifest: %w", err)
|
|
||||||
}
|
|
||||||
return &pack, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func DownloadStickerPackItem(ctx context.Context, packID, packKey []byte, stickerID uint32) ([]byte, error) {
|
|
||||||
if len(packID) != 16 {
|
|
||||||
return nil, fmt.Errorf("invalid pack ID length: %d", len(packID))
|
|
||||||
}
|
|
||||||
return downloadStickerData(ctx, fmt.Sprintf("/stickers/%x/full/%d", packID, stickerID), packKey)
|
|
||||||
}
|
|
||||||
|
|
||||||
func downloadStickerData(ctx context.Context, path string, packKey []byte) ([]byte, error) {
|
|
||||||
if len(packKey) != 32 {
|
|
||||||
return nil, fmt.Errorf("invalid pack key length: %d", len(packKey))
|
|
||||||
}
|
|
||||||
var body, decrypted []byte
|
|
||||||
resp, err := web.SendHTTPRequest(ctx, web.CDN1Hostname, http.MethodGet, path, nil)
|
|
||||||
defer web.CloseBody(resp)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to make request: %w", err)
|
|
||||||
} else if resp.StatusCode != http.StatusOK {
|
|
||||||
return nil, fmt.Errorf("unexpected status code %d", resp.StatusCode)
|
|
||||||
} else if body, err = io.ReadAll(resp.Body); err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to read response: %w", err)
|
|
||||||
} else if decrypted, err = decryptSticker(packKey, body); err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to decrypt response: %w", err)
|
|
||||||
} else {
|
|
||||||
return decrypted, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type stickerUploadAttributes struct {
|
|
||||||
ACL string `json:"acl"`
|
|
||||||
Algorithm string `json:"algorithm"`
|
|
||||||
Credential string `json:"credential"`
|
|
||||||
Date string `json:"date"`
|
|
||||||
ID int `json:"id"`
|
|
||||||
Key string `json:"key"`
|
|
||||||
Policy string `json:"policy"`
|
|
||||||
Signature string `json:"signature"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sua *stickerUploadAttributes) makeFormBody(encryptedData []byte) (*web.HTTPReqOpt, error) {
|
|
||||||
var buf bytes.Buffer
|
|
||||||
writer := multipart.NewWriter(&buf)
|
|
||||||
var closed bool
|
|
||||||
// This isn't necessary in practice, just do it to avoid linter warnings
|
|
||||||
defer func() {
|
|
||||||
if !closed {
|
|
||||||
_ = writer.Close()
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
fields := map[string]string{
|
|
||||||
"key": sua.Key,
|
|
||||||
"acl": sua.ACL,
|
|
||||||
"policy": sua.Policy,
|
|
||||||
"x-amz-algorithm": sua.Algorithm,
|
|
||||||
"x-amz-credential": sua.Credential,
|
|
||||||
"x-amz-date": sua.Date,
|
|
||||||
"Content-Type": "application/octet-stream",
|
|
||||||
}
|
|
||||||
for key, value := range fields {
|
|
||||||
err := writer.WriteField(key, value)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to write multipart field %s: %w", key, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
filePart, err := writer.CreatePart(textproto.MIMEHeader{
|
|
||||||
"Content-Type": []string{"application/octet-stream"},
|
|
||||||
"Content-Disposition": []string{`form-data; name="file"`},
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to create multipart file part: %w", err)
|
|
||||||
}
|
|
||||||
_, err = filePart.Write(encryptedData)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to write file data to multipart body: %w", err)
|
|
||||||
}
|
|
||||||
err = writer.Close()
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to close multipart writer: %w", err)
|
|
||||||
}
|
|
||||||
closed = true
|
|
||||||
return &web.HTTPReqOpt{
|
|
||||||
Body: buf.Bytes(),
|
|
||||||
ContentType: web.ContentType(writer.FormDataContentType()),
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sua *stickerUploadAttributes) upload(ctx context.Context, packKey, fileData []byte) error {
|
|
||||||
encryptedData, err := macAndAESEncrypt(fileData, deriveStickerPackKey(packKey))
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to encrypt sticker data: %w", err)
|
|
||||||
}
|
|
||||||
req, err := sua.makeFormBody(encryptedData)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to prepare request: %w", err)
|
|
||||||
}
|
|
||||||
resp, err := web.SendHTTPRequest(ctx, web.CDN1Hostname, http.MethodPost, "/", req)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
_ = resp.Body.Close()
|
|
||||||
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
|
|
||||||
return fmt.Errorf("unexpected status code %d", resp.StatusCode)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sua *stickerUploadAttributes) uploadAsync(
|
|
||||||
ctx context.Context,
|
|
||||||
packKey []byte,
|
|
||||||
getFileData func(context.Context) ([]byte, error),
|
|
||||||
sema *semaphore.Weighted,
|
|
||||||
done func(),
|
|
||||||
onError func(error),
|
|
||||||
) {
|
|
||||||
defer done()
|
|
||||||
err := sema.Acquire(ctx, 1)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer sema.Release(1)
|
|
||||||
fileData, err := getFileData(ctx)
|
|
||||||
if err == nil {
|
|
||||||
err = sua.upload(ctx, packKey, fileData)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
onError(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type stickerPackUploadAttributes struct {
|
|
||||||
PackID string `json:"packId"`
|
|
||||||
Manifest *stickerUploadAttributes `json:"manifest"`
|
|
||||||
Stickers []*stickerUploadAttributes `json:"stickers"`
|
|
||||||
}
|
|
||||||
|
|
||||||
var StickerUploadParallelism = 4
|
|
||||||
|
|
||||||
func (cli *Client) UploadStickerPack(ctx context.Context, pack *signalpb.Pack, stickerData []func(context.Context) ([]byte, error)) (packID, packKey []byte, err error) {
|
|
||||||
for i, sticker := range pack.Stickers {
|
|
||||||
if sticker.GetId() >= uint32(len(stickerData)) {
|
|
||||||
return nil, nil, fmt.Errorf("sticker ID %d at index %d is out of bounds, only %d sticker blobs provided", sticker.GetId(), i, len(stickerData))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
marshaledPack, err := proto.Marshal(pack)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, fmt.Errorf("failed to marshal pack: %w", err)
|
|
||||||
}
|
|
||||||
packKey = random.Bytes(32)
|
|
||||||
resp, err := cli.AuthedWS.SendRequest(ctx, http.MethodGet, fmt.Sprintf("/v1/sticker/pack/form/%d", len(stickerData)), nil, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, fmt.Errorf("failed to get upload form: %w", err)
|
|
||||||
}
|
|
||||||
var packAttributes stickerPackUploadAttributes
|
|
||||||
err = web.DecodeWSResponseBody(ctx, &packAttributes, resp)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, fmt.Errorf("failed to decode pack attributes: %w", err)
|
|
||||||
}
|
|
||||||
if len(packAttributes.Stickers) != len(stickerData) {
|
|
||||||
return nil, nil, fmt.Errorf("expected %d sticker upload attribute sets, got %d", len(stickerData), len(packAttributes.Stickers))
|
|
||||||
}
|
|
||||||
packID, err = hex.DecodeString(packAttributes.PackID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, fmt.Errorf("invalid pack ID in response: %w", err)
|
|
||||||
}
|
|
||||||
err = packAttributes.Manifest.upload(ctx, packKey, marshaledPack)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, fmt.Errorf("failed to upload manifest: %w", err)
|
|
||||||
}
|
|
||||||
var wg sync.WaitGroup
|
|
||||||
wg.Add(len(packAttributes.Stickers))
|
|
||||||
sema := semaphore.NewWeighted(int64(StickerUploadParallelism))
|
|
||||||
var errorList []error
|
|
||||||
var errorLock sync.Mutex
|
|
||||||
for i, attrs := range packAttributes.Stickers {
|
|
||||||
go attrs.uploadAsync(ctx, packKey, stickerData[i], sema, wg.Done, func(err error) {
|
|
||||||
errorLock.Lock()
|
|
||||||
errorList = append(errorList, fmt.Errorf("failed to upload sticker #%d: %w", i+1, err))
|
|
||||||
errorLock.Unlock()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
wg.Wait()
|
|
||||||
err = ctx.Err()
|
|
||||||
if err == nil {
|
|
||||||
err = errors.Join(errorList...)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func decryptSticker(packKey, ciphertext []byte) ([]byte, error) {
|
|
||||||
return macAndAESDecrypt(ciphertext, deriveStickerPackKey(packKey))
|
|
||||||
}
|
|
||||||
|
|
||||||
func deriveStickerPackKey(key []byte) []byte {
|
|
||||||
return exerrors.Must(hkdf.Key(sha256.New, key, make([]byte, 32), "Sticker Pack", 2*32))
|
|
||||||
}
|
|
||||||
|
|
@ -66,14 +66,12 @@ func (cli *Client) processStorageInTxn(ctx context.Context, update *StorageUpdat
|
||||||
switch data := record.StorageRecord.GetRecord().(type) {
|
switch data := record.StorageRecord.GetRecord().(type) {
|
||||||
case *signalpb.StorageRecord_Contact:
|
case *signalpb.StorageRecord_Contact:
|
||||||
log.Trace().Any("contact_record", data.Contact).Msg("Handling contact record")
|
log.Trace().Any("contact_record", data.Contact).Msg("Handling contact record")
|
||||||
aci, _ := ParseStringOrBinaryUUID(data.Contact.Aci, data.Contact.AciBinary)
|
aci, _ := uuid.Parse(data.Contact.Aci)
|
||||||
pni, _ := ParseStringOrBinaryUUID(data.Contact.Pni, data.Contact.PniBinary)
|
pni, _ := uuid.Parse(data.Contact.Pni)
|
||||||
if aci == uuid.Nil && pni == uuid.Nil {
|
if aci == uuid.Nil && pni == uuid.Nil {
|
||||||
log.Warn().
|
log.Warn().
|
||||||
Str("raw_aci", data.Contact.Aci).
|
Str("raw_aci", data.Contact.Aci).
|
||||||
Str("raw_pni", data.Contact.Pni).
|
Str("raw_pni", data.Contact.Pni).
|
||||||
Hex("raw_aci_binary", data.Contact.AciBinary).
|
|
||||||
Hex("raw_pni_binary", data.Contact.PniBinary).
|
|
||||||
Str("raw_e164", data.Contact.E164).
|
Str("raw_e164", data.Contact.E164).
|
||||||
Msg("Storage service has contact record with no ACI or PNI")
|
Msg("Storage service has contact record with no ACI or PNI")
|
||||||
continue
|
continue
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,6 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
|
|
||||||
|
|
@ -130,7 +129,6 @@ func SendHTTPRequest(ctx context.Context, host, method, path string, opt *HTTPRe
|
||||||
} else {
|
} else {
|
||||||
req.Header.Set("Content-Type", string(ContentTypeJSON))
|
req.Header.Set("Content-Type", string(ContentTypeJSON))
|
||||||
}
|
}
|
||||||
req.ContentLength = int64(len(opt.Body))
|
|
||||||
req.Header.Set("Content-Length", fmt.Sprintf("%d", len(opt.Body)))
|
req.Header.Set("Content-Length", fmt.Sprintf("%d", len(opt.Body)))
|
||||||
req.Header.Set("User-Agent", UserAgent)
|
req.Header.Set("User-Agent", UserAgent)
|
||||||
req.Header.Set("X-Signal-Agent", SignalAgent)
|
req.Header.Set("X-Signal-Agent", SignalAgent)
|
||||||
|
|
@ -141,14 +139,12 @@ func SendHTTPRequest(ctx context.Context, host, method, path string, opt *HTTPRe
|
||||||
httpReqCounter++
|
httpReqCounter++
|
||||||
log = log.With().Int("request_number", httpReqCounter).Logger()
|
log = log.With().Int("request_number", httpReqCounter).Logger()
|
||||||
log.Trace().Msg("Sending HTTP request")
|
log.Trace().Msg("Sending HTTP request")
|
||||||
start := time.Now()
|
|
||||||
resp, err := SignalHTTPClient.Do(req)
|
resp, err := SignalHTTPClient.Do(req)
|
||||||
dur := time.Since(start)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Err(err).Dur("duration", dur).Msg("Error sending request")
|
log.Err(err).Msg("Error sending request")
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
log.Debug().Int("status_code", resp.StatusCode).Dur("duration", dur).Msg("Received HTTP response")
|
log.Debug().Int("status_code", resp.StatusCode).Msg("received HTTP response")
|
||||||
return resp, nil
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue