From d4518d7f1668aaef172c740aa470b5e193115698 Mon Sep 17 00:00:00 2001 From: Volodymyr Kozieiev Date: Tue, 15 Dec 2020 16:43:41 +0200 Subject: [PATCH] resend emoji reaction (#2088) --- VERSION | 2 +- go.mod | 3 + go.sum | 29 +++ protocol/messenger.go | 166 ++++++++++++- protocol/messenger_test.go | 172 +++++++++++++ protocol/migrations/migrations.go | 228 ++++++++---------- protocol/persistence.go | 59 ++++- protocol/persistence_test.go | 79 ++++++ protocol/transport/transport.go | 2 + protocol/transport/waku/waku_service.go | 8 + protocol/transport/whisper/whisper_service.go | 8 + 11 files changed, 612 insertions(+), 144 deletions(-) diff --git a/VERSION b/VERSION index a1b8a7d1a..6ede9ee42 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.64.6 +0.64.7 diff --git a/go.mod b/go.mod index 7d39d5d0b..6c5fd6cb2 100644 --- a/go.mod +++ b/go.mod @@ -14,6 +14,8 @@ require ( github.com/btcsuite/btcd v0.20.1-beta github.com/cenkalti/backoff/v3 v3.2.2 github.com/deckarep/golang-set v1.7.1 + github.com/docker/docker v1.13.1 + github.com/docker/go-metrics v0.0.1 // indirect github.com/ethereum/go-ethereum v1.9.5 github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 // indirect github.com/go-playground/universal-translator v0.17.0 // indirect @@ -52,6 +54,7 @@ require ( github.com/russolsen/same v0.0.0-20160222130632-f089df61f51d // indirect github.com/russolsen/transit v0.0.0-20180705123435-0794b4c4505a github.com/status-im/doubleratchet v3.0.0+incompatible + github.com/status-im/go-ethereum v1.9.1 // indirect github.com/status-im/keycard-go v0.0.0-20200107115650-f38e9a19958e // indirect github.com/status-im/markdown v0.0.0-20201022101546-c0cbdd5763bf github.com/status-im/migrate/v4 v4.6.2-status.2 diff --git a/go.sum b/go.sum index e56366a11..e96823152 100644 --- a/go.sum +++ b/go.sum @@ -127,6 +127,8 @@ github.com/docker/engine v1.4.2-0.20190717161051-705d9623b7c1 h1:HjO0YFIGk26fADK github.com/docker/engine v1.4.2-0.20190717161051-705d9623b7c1/go.mod h1:3CPr2caMgTHxxIAZgEMd3uLYPDlRvPqCpyeRf6ncPcY= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= +github.com/docker/go-metrics v0.0.1 h1:AgB/0SvBxihN0X8OR4SjsblXkbMvalQ8cjmtKQ2rQV8= +github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw= github.com/docker/go-units v0.3.3 h1:Xk8S3Xj5sLGlG5g67hJmYMmUgXv5N4PhkjJHHqrwnTk= github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= @@ -144,6 +146,7 @@ github.com/elastic/gosigar v0.10.4 h1:6jfw75dsoflhBMRdO6QPzQUgLqUYTsQQQRkkcsHsuP github.com/elastic/gosigar v0.10.4/go.mod h1:cdorVVzy1fhmEqmtgqkoE3bYtCfSCkVyjTyCIo22xvs= github.com/elazarl/go-bindata-assetfs v1.0.0/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/ethereum/go-ethereum v1.8.20/go.mod h1:PwpWDrCLZrV+tfrhqqF6kPknbISMHaJv9Ln3kPCZLwY= github.com/ethereum/go-ethereum v1.9.2/go.mod h1:PwpWDrCLZrV+tfrhqqF6kPknbISMHaJv9Ln3kPCZLwY= @@ -205,6 +208,13 @@ github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.4 h1:87PNWwrRvUSnqS4dlcBU/ftvOIBep4sYuBLlh6rX2wk= github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1 h1:ZFgWrT+bLgsYPirOnRfKLYJLvssAegOj/hgyMFdJZe0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4= @@ -216,6 +226,7 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -580,10 +591,12 @@ github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXP github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM= github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= github.com/prometheus/client_golang v1.2.1 h1:JnMpQc6ppsNgw9QPAGF6Dod479itz7lvlsMzzNayLOI= github.com/prometheus/client_golang v1.2.1/go.mod h1:XMU6Z2MjaRKVu/dC1qupJI9SiNkDYzz3xecMgSW/F+U= github.com/prometheus/client_golang v1.5.0 h1:Ctq0iGpCmr3jeP77kbF2UxgvRwzWWz+4Bh9/vJTyg1A= github.com/prometheus/client_golang v1.5.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= +github.com/prometheus/client_golang v1.8.0 h1:zvJNkoCFAnYFNC24FV8nW4JdRJ3GIFcLbg65lL/JDcw= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -594,6 +607,7 @@ github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6T github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= github.com/prometheus/common v0.7.0 h1:L+1lyG48J1zAQXA3RBX/nG/B3gjlHq0zTt2tlbJLyCY= github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= github.com/prometheus/common v0.9.1 h1:KOMtN28tlbam3/7ZKEYKHhKoJZYYj3gMH4uc62x7X7U= @@ -602,6 +616,7 @@ github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= github.com/prometheus/procfs v0.0.5 h1:3+auTFlqw+ZaQYJARz6ArODtkaIwtvBTx3N2NehQlL8= github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= github.com/prometheus/procfs v0.0.8 h1:+fpWZdT24pJBiqJdAwYBjPSk+5YmQzYNPYzQsdzLkt8= @@ -652,6 +667,8 @@ github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DM github.com/src-d/envconfig v1.0.0/go.mod h1:Q9YQZ7BKITldTBnoxsE5gOeB5y66RyPXeue/R4aaNBc= github.com/status-im/doubleratchet v3.0.0+incompatible h1:aJ1ejcSERpSzmWZBgtfYtiU2nF0Q8ZkGyuEPYETXkCY= github.com/status-im/doubleratchet v3.0.0+incompatible/go.mod h1:1sqR0+yhiM/bd+wrdX79AOt2csZuJOni0nUDzKNuqOU= +github.com/status-im/go-ethereum v1.9.1 h1:N3E3g++Isr4OORPVPwWFlaHp+3EOV9X4A88MbcRsk2Y= +github.com/status-im/go-ethereum v1.9.1/go.mod h1:rdSZTVW2L1V6dsRpW77o4gwqWRUYfb/e9nNHcIgVEO4= github.com/status-im/go-ethereum v1.9.5-status.9 h1:qKTXRRDuF+Exqk5QEo0E2vNwqPi9+g6vAQ4Y5ZK7c4Q= github.com/status-im/go-ethereum v1.9.5-status.9/go.mod h1:YyH5DKB6+z+Vaya7eIm67pnuPZ1oiUMbbsZW41ktN0g= github.com/status-im/go-multiaddr-ethv4 v1.2.0 h1:OT84UsUzTCwguqCpJqkrCMiL4VZ1SvUtH9a5MsZupBk= @@ -826,6 +843,7 @@ golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190426135247-a129542de9ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -884,6 +902,7 @@ google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRn google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20191115221424-83cc0476cb11 h1:51D++eCgOHufw5VfDE9Uzqyyc+OyQIjb9hkYy9LN5Fk= google.golang.org/genproto v0.0.0-20191115221424-83cc0476cb11/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1 h1:Hz2g2wirWK7H0qIIhGIqRGTuMwTE8HEKFnDZZ7lm9NU= @@ -891,6 +910,16 @@ google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiq google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1 h1:wdKvqQk7IttEw92GoRyKG2IDrUIpgpj6H6m81yfeMW0= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/protocol/messenger.go b/protocol/messenger.go index bc5754439..093374890 100644 --- a/protocol/messenger.go +++ b/protocol/messenger.go @@ -6,6 +6,7 @@ import ( "database/sql" "encoding/hex" "io/ioutil" + "math" "math/rand" "os" "reflect" @@ -42,6 +43,9 @@ const PubKeyStringLength = 132 const transactionSentTxt = "Transaction sent" +const emojiResendMinDelay = 30 +const emojiResendMaxCount = 3 + // Messenger is a entity managing chats and messages. // It acts as a bridge between the application and encryption // layers. @@ -88,6 +92,45 @@ type dbConfig struct { dbKey string } +type EnvelopeEventsInterceptor struct { + EnvelopeEventsHandler transport.EnvelopeEventsHandler + Messenger *Messenger +} + +// EnvelopeSent triggered when envelope delivered at least to 1 peer. +func (interceptor EnvelopeEventsInterceptor) EnvelopeSent(identifiers [][]byte) { + if interceptor.Messenger != nil { + var ids []string + for _, identifierBytes := range identifiers { + ids = append(ids, types.EncodeHex(identifierBytes)) + } + + err := interceptor.Messenger.processSentMessages(ids) + if err != nil { + interceptor.Messenger.logger.Info("Messenger failed to process sent messages", zap.Error(err)) + } + } + interceptor.EnvelopeEventsHandler.EnvelopeSent(identifiers) +} + +// EnvelopeExpired triggered when envelope is expired but wasn't delivered to any peer. +func (interceptor EnvelopeEventsInterceptor) EnvelopeExpired(identifiers [][]byte, err error) { + //we don't track expired events in Messenger, so just redirect to handler + interceptor.EnvelopeEventsHandler.EnvelopeExpired(identifiers, err) +} + +// MailServerRequestCompleted triggered when the mailserver sends a message to notify that the request has been completed +func (interceptor EnvelopeEventsInterceptor) MailServerRequestCompleted(requestID types.Hash, lastEnvelopeHash types.Hash, cursor []byte, err error) { + //we don't track mailserver requests in Messenger, so just redirect to handler + interceptor.EnvelopeEventsHandler.MailServerRequestCompleted(requestID, lastEnvelopeHash, cursor, err) +} + +// MailServerRequestExpired triggered when the mailserver request expires +func (interceptor EnvelopeEventsInterceptor) MailServerRequestExpired(hash types.Hash) { + //we don't track mailserver requests in Messenger, so just redirect to handler + interceptor.EnvelopeEventsHandler.MailServerRequestExpired(hash) +} + func NewMessenger( identity *ecdsa.PrivateKey, node types.Node, @@ -248,11 +291,87 @@ func NewMessenger( logger: logger, } - logger.Debug("messages persistence", zap.Bool("enabled", c.messagesPersistenceEnabled)) + if c.envelopesMonitorConfig != nil { + interceptor := EnvelopeEventsInterceptor{c.envelopesMonitorConfig.EnvelopeEventsHandler, messenger} + err := messenger.transport.SetEnvelopeEventsHandler(interceptor) + if err != nil { + logger.Info("Unable to set envelopes event handler", zap.Error(err)) + } + } + logger.Debug("messages persistence", zap.Bool("enabled", c.messagesPersistenceEnabled)) return messenger, nil } +func (m *Messenger) processSentMessages(ids []string) error { + m.mutex.Lock() + defer m.mutex.Unlock() + + for _, id := range ids { + rawMessage, err := m.persistence.RawMessageByID(id) + if err != nil { + return errors.Wrapf(err, "Can't get raw message with id %v", id) + } + + rawMessage.Sent = true + + err = m.persistence.SaveRawMessage(rawMessage) + if err != nil { + return errors.Wrapf(err, "Can't save raw message marked as sent") + } + } + + return nil +} + +func shouldResendEmojiReaction(message *common.RawMessage, t TimeSource) (bool, error) { + if message.MessageType != protobuf.ApplicationMetadataMessage_EMOJI_REACTION { + return false, errors.New("Should resend only emoji reactions") + } + + if message.Sent { + return false, errors.New("Should resend only non-sent messages") + } + + if message.SendCount > emojiResendMaxCount { + return false, nil + } + + //exponential backoff depends on how many attempts to send message already made + backoff := uint64(math.Pow(2, float64(message.SendCount-1))) * emojiResendMinDelay * uint64(time.Second) + backoffElapsed := t.GetCurrentTime() > (message.LastSent + backoff) + return backoffElapsed, nil +} + +func (m *Messenger) resendExpiredEmojiReactions() error { + ids, err := m.persistence.ExpiredEmojiReactionsIDs(emojiResendMaxCount) + if err != nil { + return errors.Wrapf(err, "Can't get expired reactions from db") + } + + for _, id := range ids { + rawMessage, err := m.persistence.RawMessageByID(id) + if err != nil { + return errors.Wrapf(err, "Can't get raw message with id %v", id) + } + + if ok, err := shouldResendEmojiReaction(rawMessage, m.getTimesource()); ok { + err = m.persistence.SaveRawMessage(rawMessage) + if err != nil { + return errors.Wrapf(err, "Can't save raw message marked as non-expired") + } + + err = m.reSendRawMessage(context.Background(), rawMessage.ID) + if err != nil { + return errors.Wrapf(err, "Can't resend expired message with id %v", rawMessage.ID) + } + } else { + return err + } + } + return nil +} + func (m *Messenger) Start() error { m.logger.Info("starting messenger", zap.String("identity", types.EncodeHex(crypto.FromECDSAPub(&m.identity.PublicKey)))) // Start push notification server @@ -288,6 +407,7 @@ func (m *Messenger) Start() error { m.handleEncryptionLayerSubscriptions(subscriptions) m.handleConnectionChange(m.online()) m.watchConnectionChange() + m.watchExpiredEmojis() return nil } @@ -297,7 +417,6 @@ func (m *Messenger) handleConnectionChange(online bool) { if m.pushNotificationClient != nil { m.pushNotificationClient.Online() } - } else { if m.pushNotificationClient != nil { m.pushNotificationClient.Offline() @@ -426,9 +545,27 @@ func (m *Messenger) watchConnectionChange() { case <-m.quit: return } - } + }() +} +// watchExpiredEmojis regularly checks for expired emojis and invoke their resending +func (m *Messenger) watchExpiredEmojis() { + m.logger.Debug("watching expired emojis") + go func() { + for { + select { + case <-time.After(time.Second): + if m.online() { + err := m.resendExpiredEmojiReactions() + if err != nil { + m.logger.Debug("Error when resending expired emoji reactions", zap.Error(err)) + } + } + case <-m.quit: + return + } + } }() } @@ -1545,11 +1682,8 @@ func (m *Messenger) GetContactByID(pubKey string) *Contact { return m.allContacts[pubKey] } -// ReSendChatMessage pulls a message from the database and sends it again -func (m *Messenger) ReSendChatMessage(ctx context.Context, messageID string) error { - m.mutex.Lock() - defer m.mutex.Unlock() - +// pull a message from the database and send it again +func (m *Messenger) reSendRawMessage(ctx context.Context, messageID string) error { message, err := m.persistence.RawMessageByID(messageID) if err != nil { return err @@ -1566,10 +1700,19 @@ func (m *Messenger) ReSendChatMessage(ctx context.Context, messageID string) err MessageType: message.MessageType, Recipients: message.Recipients, ResendAutomatically: message.ResendAutomatically, + SendCount: message.SendCount, }) return err } +// ReSendChatMessage pulls a message from the database and sends it again +func (m *Messenger) ReSendChatMessage(ctx context.Context, messageID string) error { + m.mutex.Lock() + defer m.mutex.Unlock() + + return m.reSendRawMessage(ctx, messageID) +} + func (m *Messenger) hasPairedDevices() bool { var count int for _, i := range m.allInstallations { @@ -1691,6 +1834,7 @@ func (m *Messenger) dispatchMessage(ctx context.Context, spec common.RawMessage) } spec.ID = types.EncodeHex(id) spec.SendCount++ + spec.LastSent = m.getTimesource().GetCurrentTime() err = m.persistence.SaveRawMessage(&spec) if err != nil { return nil, err @@ -3517,10 +3661,6 @@ func (m *Messenger) getTimesource() TimeSource { return m.transport } -func (m *Messenger) Timesource() TimeSource { - return m.getTimesource() -} - // AddPushNotificationsServer adds a push notification server func (m *Messenger) AddPushNotificationsServer(ctx context.Context, publicKey *ecdsa.PublicKey, serverType pushnotificationclient.ServerType) error { if m.pushNotificationClient == nil { @@ -3748,7 +3888,7 @@ func (m *Messenger) SendEmojiReaction(ctx context.Context, chatID, messageID str err = m.persistence.SaveEmojiReaction(emojiR) if err != nil { - return nil, err + return nil, errors.Wrap(err, "Can't save emoji reaction in db") } return &response, nil diff --git a/protocol/messenger_test.go b/protocol/messenger_test.go index affea705e..86afcc65e 100644 --- a/protocol/messenger_test.go +++ b/protocol/messenger_test.go @@ -2173,6 +2173,178 @@ func (s *MessengerSuite) TestRequestHistoricMessagesRequest() { s.NotEmpty(shh.req.Bloom) } +func (s *MessengerSuite) TestSentEventTracking() { + + //when message sent, its sent field should be "false" until we got confirmation + chat := CreatePublicChat("test-chat", s.m.transport) + err := s.m.SaveChat(&chat) + s.NoError(err) + inputMessage := buildTestMessage(chat) + + _, err = s.m.SendChatMessage(context.Background(), inputMessage) + s.NoError(err) + + rawMessage, err := s.m.persistence.RawMessageByID(inputMessage.ID) + s.NoError(err) + s.False(rawMessage.Sent) + + //when message sent, its sent field should be true after we got confirmation + err = s.m.processSentMessages([]string{inputMessage.ID}) + s.NoError(err) + + rawMessage, err = s.m.persistence.RawMessageByID(inputMessage.ID) + s.NoError(err) + s.True(rawMessage.Sent) +} + +func (s *MessengerSuite) TestLastSentField() { + //send message + chat := CreatePublicChat("test-chat", s.m.transport) + err := s.m.SaveChat(&chat) + s.NoError(err) + inputMessage := buildTestMessage(chat) + + _, err = s.m.SendChatMessage(context.Background(), inputMessage) + s.NoError(err) + + rawMessage, err := s.m.persistence.RawMessageByID(inputMessage.ID) + s.NoError(err) + s.Equal(1, rawMessage.SendCount) + + //make sure LastSent is set + s.NotEqual(uint64(0), rawMessage.LastSent, "rawMessage.LastSent should be non-zero after sending") +} + +func (s *MessengerSuite) TestShouldResendEmoji() { + // shouldn't try to resend non-emoji messages. + ok, err := shouldResendEmojiReaction(&common.RawMessage{ + MessageType: protobuf.ApplicationMetadataMessage_CONTACT_UPDATE, + Sent: false, + SendCount: 2, + }, s.m.getTimesource()) + s.Error(err) + s.False(ok) + + // shouldn't try to resend already sent message + ok, err = shouldResendEmojiReaction(&common.RawMessage{ + MessageType: protobuf.ApplicationMetadataMessage_EMOJI_REACTION, + Sent: true, + SendCount: 1, + }, s.m.getTimesource()) + s.Error(err) + s.False(ok) + + // messages that already sent to many times shouldn't be resend + ok, err = shouldResendEmojiReaction(&common.RawMessage{ + MessageType: protobuf.ApplicationMetadataMessage_EMOJI_REACTION, + Sent: false, + SendCount: emojiResendMaxCount + 1, + }, s.m.getTimesource()) + s.NoError(err) + s.False(ok) + + // message sent one time CAN'T be resend in 15 seconds (only after 30) + ok, err = shouldResendEmojiReaction(&common.RawMessage{ + MessageType: protobuf.ApplicationMetadataMessage_EMOJI_REACTION, + Sent: false, + SendCount: 1, + LastSent: s.m.getTimesource().GetCurrentTime() - 15*uint64(time.Second), + }, s.m.getTimesource()) + s.NoError(err) + s.False(ok) + + // message sent one time CAN be resend in 35 seconds + ok, err = shouldResendEmojiReaction(&common.RawMessage{ + MessageType: protobuf.ApplicationMetadataMessage_EMOJI_REACTION, + Sent: false, + SendCount: 1, + LastSent: s.m.getTimesource().GetCurrentTime() - 35*uint64(time.Second), + }, s.m.getTimesource()) + s.NoError(err) + s.True(ok) + + // message sent three times CAN'T be resend in 100 seconds (only after 120) + ok, err = shouldResendEmojiReaction(&common.RawMessage{ + MessageType: protobuf.ApplicationMetadataMessage_EMOJI_REACTION, + Sent: false, + SendCount: 3, + LastSent: s.m.getTimesource().GetCurrentTime() - 100*uint64(time.Second), + }, s.m.getTimesource()) + s.NoError(err) + s.False(ok) + + // message sent tow times CAN be resend in 65 seconds + ok, err = shouldResendEmojiReaction(&common.RawMessage{ + MessageType: protobuf.ApplicationMetadataMessage_EMOJI_REACTION, + Sent: false, + SendCount: 3, + LastSent: s.m.getTimesource().GetCurrentTime() - 125*uint64(time.Second), + }, s.m.getTimesource()) + s.NoError(err) + s.True(ok) +} + +func (s *MessengerSuite) TestMessageSent() { + //send message + chat := CreatePublicChat("test-chat", s.m.transport) + err := s.m.SaveChat(&chat) + s.NoError(err) + inputMessage := buildTestMessage(chat) + + _, err = s.m.SendChatMessage(context.Background(), inputMessage) + s.NoError(err) + + rawMessage, err := s.m.persistence.RawMessageByID(inputMessage.ID) + s.NoError(err) + s.Equal(1, rawMessage.SendCount) + s.False(rawMessage.Sent) + + //imitate chat message sent + err = s.m.processSentMessages([]string{inputMessage.ID}) + s.NoError(err) + + rawMessage, err = s.m.persistence.RawMessageByID(inputMessage.ID) + s.NoError(err) + s.Equal(1, rawMessage.SendCount) + s.True(rawMessage.Sent) +} + +func (s *MessengerSuite) TestResendExpiredEmojis() { + //send message + chat := CreatePublicChat("test-chat", s.m.transport) + err := s.m.SaveChat(&chat) + s.NoError(err) + inputMessage := buildTestMessage(chat) + + _, err = s.m.SendChatMessage(context.Background(), inputMessage) + s.NoError(err) + + //create emoji + _, err = s.m.SendEmojiReaction(context.Background(), chat.ID, inputMessage.ID, protobuf.EmojiReaction_SAD) + s.Require().NoError(err) + + ids, err := s.m.persistence.RawMessagesIDsByType(protobuf.ApplicationMetadataMessage_EMOJI_REACTION) + s.Require().NoError(err) + emojiID := ids[0] + + //check that emoji was sent one time + rawMessage, err := s.m.persistence.RawMessageByID(emojiID) + s.NoError(err) + s.False(rawMessage.Sent) + s.Equal(1, rawMessage.SendCount) + + //imitate that more than 30 seconds passed since message was sent + rawMessage.LastSent = rawMessage.LastSent - 35*uint64(time.Second) + err = s.m.persistence.SaveRawMessage(rawMessage) + s.NoError(err) + time.Sleep(2 * time.Second) + + //make sure it was resent and SendCount incremented + rawMessage, err = s.m.persistence.RawMessageByID(emojiID) + s.NoError(err) + s.Equal(2, rawMessage.SendCount) +} + type MessageHandlerSuite struct { suite.Suite diff --git a/protocol/migrations/migrations.go b/protocol/migrations/migrations.go index 711bc435a..85abbc96e 100644 --- a/protocol/migrations/migrations.go +++ b/protocol/migrations/migrations.go @@ -51,7 +51,7 @@ import ( func bindataRead(data []byte, name string) ([]byte, error) { gz, err := gzip.NewReader(bytes.NewBuffer(data)) if err != nil { - return nil, fmt.Errorf("read %q: %v", name, err) + return nil, fmt.Errorf("read %q: %w", name, err) } var buf bytes.Buffer @@ -59,7 +59,7 @@ func bindataRead(data []byte, name string) ([]byte, error) { clErr := gz.Close() if err != nil { - return nil, fmt.Errorf("read %q: %v", name, err) + return nil, fmt.Errorf("read %q: %w", name, err) } if clErr != nil { return nil, err @@ -115,7 +115,7 @@ func _000001_initDownDbSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "000001_init.down.db.sql", size: 65, mode: os.FileMode(0664), modTime: time.Unix(1604073469, 0)} + info := bindataFileInfo{name: "000001_init.down.db.sql", size: 65, mode: os.FileMode(0644), modTime: time.Unix(1604483964, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x5e, 0xbb, 0x3f, 0x1, 0x75, 0x19, 0x70, 0x86, 0xa7, 0x34, 0x40, 0x17, 0x34, 0x3e, 0x18, 0x51, 0x79, 0xd4, 0x22, 0xad, 0x8f, 0x80, 0xcc, 0xa6, 0xcc, 0x6, 0x2b, 0x62, 0x2, 0x47, 0xba, 0xf9}} return a, nil } @@ -135,7 +135,7 @@ func _000001_initUpDbSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "000001_init.up.db.sql", size: 2719, mode: os.FileMode(0664), modTime: time.Unix(1604073469, 0)} + info := bindataFileInfo{name: "000001_init.up.db.sql", size: 2719, mode: os.FileMode(0644), modTime: time.Unix(1604483964, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x60, 0xdc, 0xeb, 0xe, 0xc2, 0x4f, 0x75, 0xa, 0xf6, 0x3e, 0xc7, 0xc4, 0x4, 0xe2, 0xe1, 0xa4, 0x73, 0x2f, 0x4a, 0xad, 0x1a, 0x0, 0xc3, 0x93, 0x9d, 0x77, 0x3e, 0x31, 0x91, 0x77, 0x2e, 0xc8}} return a, nil } @@ -155,7 +155,7 @@ func _000002_add_last_ens_clock_valueDownSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "000002_add_last_ens_clock_value.down.sql", size: 0, mode: os.FileMode(0664), modTime: time.Unix(1604073469, 0)} + info := bindataFileInfo{name: "000002_add_last_ens_clock_value.down.sql", size: 0, mode: os.FileMode(0644), modTime: time.Unix(1604483964, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55}} return a, nil } @@ -175,7 +175,7 @@ func _000002_add_last_ens_clock_valueUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "000002_add_last_ens_clock_value.up.sql", size: 77, mode: os.FileMode(0664), modTime: time.Unix(1604073469, 0)} + info := bindataFileInfo{name: "000002_add_last_ens_clock_value.up.sql", size: 77, mode: os.FileMode(0644), modTime: time.Unix(1604483964, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x4d, 0x3, 0x8f, 0xd5, 0x85, 0x83, 0x47, 0xbe, 0xf9, 0x82, 0x7e, 0x81, 0xa4, 0xbd, 0xaa, 0xd5, 0x98, 0x18, 0x5, 0x2d, 0x82, 0x42, 0x3b, 0x3, 0x50, 0xc3, 0x1e, 0x84, 0x35, 0xf, 0xb6, 0x2b}} return a, nil } @@ -195,7 +195,7 @@ func _1586358095_add_replaceDownSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1586358095_add_replace.down.sql", size: 0, mode: os.FileMode(0664), modTime: time.Unix(1604073469, 0)} + info := bindataFileInfo{name: "1586358095_add_replace.down.sql", size: 0, mode: os.FileMode(0644), modTime: time.Unix(1604483964, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55}} return a, nil } @@ -215,7 +215,7 @@ func _1586358095_add_replaceUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1586358095_add_replace.up.sql", size: 224, mode: os.FileMode(0664), modTime: time.Unix(1604073469, 0)} + info := bindataFileInfo{name: "1586358095_add_replace.up.sql", size: 224, mode: os.FileMode(0644), modTime: time.Unix(1604483964, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xd2, 0xb3, 0xa9, 0xc7, 0x7f, 0x9d, 0x8f, 0x43, 0x8c, 0x9e, 0x58, 0x8d, 0x44, 0xbc, 0xfa, 0x6b, 0x5f, 0x3f, 0x5a, 0xbe, 0xe8, 0xb1, 0x16, 0xf, 0x91, 0x2a, 0xa0, 0x71, 0xbb, 0x8d, 0x6b, 0xcb}} return a, nil } @@ -235,7 +235,7 @@ func _1588665364_add_image_dataDownSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1588665364_add_image_data.down.sql", size: 0, mode: os.FileMode(0664), modTime: time.Unix(1604073469, 0)} + info := bindataFileInfo{name: "1588665364_add_image_data.down.sql", size: 0, mode: os.FileMode(0644), modTime: time.Unix(1604483964, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55}} return a, nil } @@ -255,7 +255,7 @@ func _1588665364_add_image_dataUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1588665364_add_image_data.up.sql", size: 186, mode: os.FileMode(0664), modTime: time.Unix(1604073469, 0)} + info := bindataFileInfo{name: "1588665364_add_image_data.up.sql", size: 186, mode: os.FileMode(0644), modTime: time.Unix(1604483964, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xd6, 0xc6, 0x35, 0xb4, 0x4c, 0x39, 0x96, 0x29, 0x30, 0xda, 0xf4, 0x8f, 0xcb, 0xf1, 0x9f, 0x84, 0xdc, 0x88, 0xd4, 0xd5, 0xbc, 0xb6, 0x5b, 0x46, 0x78, 0x67, 0x76, 0x1a, 0x5, 0x36, 0xdc, 0xe5}} return a, nil } @@ -275,7 +275,7 @@ func _1589365189_add_pow_targetDownSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1589365189_add_pow_target.down.sql", size: 0, mode: os.FileMode(0664), modTime: time.Unix(1604073469, 0)} + info := bindataFileInfo{name: "1589365189_add_pow_target.down.sql", size: 0, mode: os.FileMode(0644), modTime: time.Unix(1604483964, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55}} return a, nil } @@ -295,7 +295,7 @@ func _1589365189_add_pow_targetUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1589365189_add_pow_target.up.sql", size: 66, mode: os.FileMode(0664), modTime: time.Unix(1604073469, 0)} + info := bindataFileInfo{name: "1589365189_add_pow_target.up.sql", size: 66, mode: os.FileMode(0644), modTime: time.Unix(1606832395, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x4e, 0x3a, 0xe2, 0x2e, 0x7d, 0xaf, 0xbb, 0xcc, 0x21, 0xa1, 0x7a, 0x41, 0x9a, 0xd0, 0xbb, 0xa9, 0xc8, 0x35, 0xf9, 0x32, 0x34, 0x46, 0x44, 0x9a, 0x86, 0x40, 0x7c, 0xb9, 0x23, 0xc7, 0x3, 0x3f}} return a, nil } @@ -315,7 +315,7 @@ func _1591277220_add_index_messagesDownSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1591277220_add_index_messages.down.sql", size: 237, mode: os.FileMode(0664), modTime: time.Unix(1604073469, 0)} + info := bindataFileInfo{name: "1591277220_add_index_messages.down.sql", size: 237, mode: os.FileMode(0644), modTime: time.Unix(1604483964, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x79, 0xe5, 0x42, 0x56, 0x64, 0x1d, 0xb7, 0x8a, 0x1b, 0x0, 0x99, 0xf0, 0x18, 0x8c, 0x69, 0xe3, 0x14, 0x3a, 0x7f, 0x78, 0xfe, 0xe3, 0x2e, 0xcb, 0x6e, 0x5c, 0x8c, 0x1f, 0x7b, 0xfc, 0x21, 0xc7}} return a, nil } @@ -335,7 +335,7 @@ func _1591277220_add_index_messagesUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1591277220_add_index_messages.up.sql", size: 240, mode: os.FileMode(0664), modTime: time.Unix(1604073469, 0)} + info := bindataFileInfo{name: "1591277220_add_index_messages.up.sql", size: 240, mode: os.FileMode(0644), modTime: time.Unix(1604483964, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x9c, 0xfe, 0xbe, 0xd5, 0xb8, 0x8f, 0xdd, 0xef, 0xbb, 0xa8, 0xad, 0x7f, 0xed, 0x5b, 0x5b, 0x2f, 0xe6, 0x82, 0x27, 0x78, 0x1f, 0xb9, 0x57, 0xdc, 0x8, 0xc2, 0xb2, 0xa9, 0x9a, 0x4, 0xe1, 0x7a}} return a, nil } @@ -355,7 +355,7 @@ func _1593087212_add_mute_chat_and_raw_message_fieldsDownSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1593087212_add_mute_chat_and_raw_message_fields.down.sql", size: 0, mode: os.FileMode(0664), modTime: time.Unix(1604073469, 0)} + info := bindataFileInfo{name: "1593087212_add_mute_chat_and_raw_message_fields.down.sql", size: 0, mode: os.FileMode(0644), modTime: time.Unix(1604483964, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55}} return a, nil } @@ -375,7 +375,7 @@ func _1593087212_add_mute_chat_and_raw_message_fieldsUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1593087212_add_mute_chat_and_raw_message_fields.up.sql", size: 215, mode: os.FileMode(0664), modTime: time.Unix(1604073469, 0)} + info := bindataFileInfo{name: "1593087212_add_mute_chat_and_raw_message_fields.up.sql", size: 215, mode: os.FileMode(0644), modTime: time.Unix(1606832887, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x73, 0x99, 0x61, 0xd1, 0xaa, 0xb4, 0xbf, 0xaf, 0xd7, 0x20, 0x17, 0x40, 0xf9, 0x2, 0xfb, 0xcc, 0x40, 0x2a, 0xd, 0x86, 0x36, 0x30, 0x88, 0x89, 0x25, 0x80, 0x42, 0xb0, 0x5b, 0xe9, 0x73, 0x78}} return a, nil } @@ -395,7 +395,7 @@ func _1595862781_add_audio_dataDownSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1595862781_add_audio_data.down.sql", size: 0, mode: os.FileMode(0664), modTime: time.Unix(1604073469, 0)} + info := bindataFileInfo{name: "1595862781_add_audio_data.down.sql", size: 0, mode: os.FileMode(0644), modTime: time.Unix(1604483964, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55}} return a, nil } @@ -415,7 +415,7 @@ func _1595862781_add_audio_dataUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1595862781_add_audio_data.up.sql", size: 246, mode: os.FileMode(0664), modTime: time.Unix(1604073469, 0)} + info := bindataFileInfo{name: "1595862781_add_audio_data.up.sql", size: 246, mode: os.FileMode(0644), modTime: time.Unix(1604483964, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xae, 0xd2, 0xee, 0x55, 0xfb, 0x36, 0xa4, 0x92, 0x66, 0xe, 0x81, 0x62, 0x1e, 0x7a, 0x69, 0xa, 0xd5, 0x4b, 0xa5, 0x6a, 0x8d, 0x1d, 0xce, 0xf3, 0x3e, 0xc0, 0x5f, 0x9c, 0x66, 0x1b, 0xb4, 0xed}} return a, nil } @@ -435,7 +435,7 @@ func _1595865249_create_emoji_reactions_tableDownSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1595865249_create_emoji_reactions_table.down.sql", size: 27, mode: os.FileMode(0664), modTime: time.Unix(1604073469, 0)} + info := bindataFileInfo{name: "1595865249_create_emoji_reactions_table.down.sql", size: 27, mode: os.FileMode(0644), modTime: time.Unix(1604483964, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x6f, 0xbb, 0xdb, 0x8c, 0xd1, 0x17, 0x1b, 0x19, 0x2a, 0x80, 0xc6, 0xb1, 0xc5, 0x47, 0x74, 0x97, 0x32, 0x30, 0x5, 0xa9, 0x9c, 0xa7, 0x60, 0xa, 0xfe, 0xfb, 0x41, 0x6b, 0x25, 0xad, 0x84, 0x20}} return a, nil } @@ -455,7 +455,7 @@ func _1595865249_create_emoji_reactions_tableUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1595865249_create_emoji_reactions_table.up.sql", size: 300, mode: os.FileMode(0664), modTime: time.Unix(1604073469, 0)} + info := bindataFileInfo{name: "1595865249_create_emoji_reactions_table.up.sql", size: 300, mode: os.FileMode(0644), modTime: time.Unix(1604483964, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x3e, 0xc5, 0x43, 0x5c, 0x3d, 0x53, 0x43, 0x2c, 0x1a, 0xa5, 0xb6, 0xbf, 0x7, 0x4, 0x5a, 0x3e, 0x40, 0x8b, 0xa4, 0x57, 0x12, 0x58, 0xbc, 0x42, 0xe2, 0xc3, 0xde, 0x76, 0x98, 0x80, 0xe2, 0xbe}} return a, nil } @@ -475,7 +475,7 @@ func _1596805115_create_group_chat_invitations_tableDownSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1596805115_create_group_chat_invitations_table.down.sql", size: 34, mode: os.FileMode(0664), modTime: time.Unix(1604073469, 0)} + info := bindataFileInfo{name: "1596805115_create_group_chat_invitations_table.down.sql", size: 34, mode: os.FileMode(0644), modTime: time.Unix(1604483964, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x6b, 0x5a, 0x17, 0xd8, 0x8d, 0xb3, 0xfe, 0xcb, 0xb6, 0xc0, 0xcb, 0x14, 0x68, 0x8c, 0x5b, 0x18, 0xf8, 0x7d, 0xc9, 0x2c, 0xa6, 0x41, 0xc9, 0x71, 0xeb, 0x3f, 0xc6, 0xa, 0x45, 0xee, 0x5d, 0x2a}} return a, nil } @@ -495,7 +495,7 @@ func _1596805115_create_group_chat_invitations_tableUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1596805115_create_group_chat_invitations_table.up.sql", size: 231, mode: os.FileMode(0664), modTime: time.Unix(1604073469, 0)} + info := bindataFileInfo{name: "1596805115_create_group_chat_invitations_table.up.sql", size: 231, mode: os.FileMode(0644), modTime: time.Unix(1604483964, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x6d, 0xb1, 0x14, 0x6d, 0x54, 0x28, 0x67, 0xc3, 0x23, 0x6a, 0xfc, 0x80, 0xdf, 0x9e, 0x4c, 0x35, 0x36, 0xf, 0xf8, 0xf3, 0x5f, 0xae, 0xad, 0xb, 0xc1, 0x51, 0x8e, 0x17, 0x7, 0xe5, 0x7f, 0x91}} return a, nil } @@ -515,7 +515,7 @@ func _1597322655_add_invitation_admin_chat_fieldUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1597322655_add_invitation_admin_chat_field.up.sql", size: 54, mode: os.FileMode(0664), modTime: time.Unix(1604073469, 0)} + info := bindataFileInfo{name: "1597322655_add_invitation_admin_chat_field.up.sql", size: 54, mode: os.FileMode(0644), modTime: time.Unix(1604483964, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xa9, 0x7a, 0xa0, 0xf2, 0xdb, 0x13, 0x91, 0x91, 0xa8, 0x34, 0x1a, 0xa1, 0x49, 0x68, 0xd5, 0xae, 0x2c, 0xd8, 0xd5, 0xea, 0x8f, 0x8c, 0xc7, 0x2, 0x4e, 0x58, 0x2c, 0x3a, 0x14, 0xd4, 0x4f, 0x2c}} return a, nil } @@ -535,7 +535,7 @@ func _1597757544_add_nicknameUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1597757544_add_nickname.up.sql", size: 52, mode: os.FileMode(0664), modTime: time.Unix(1604073469, 0)} + info := bindataFileInfo{name: "1597757544_add_nickname.up.sql", size: 52, mode: os.FileMode(0644), modTime: time.Unix(1604483964, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xf4, 0xa2, 0x64, 0x50, 0xc5, 0x4, 0xb9, 0x8b, 0xd1, 0x18, 0x9b, 0xc3, 0x91, 0x36, 0x2a, 0x1f, 0xc3, 0x6c, 0x2d, 0x92, 0xf8, 0x5e, 0xff, 0xb1, 0x59, 0x61, 0x2, 0x1c, 0xe1, 0x85, 0x90, 0xa4}} return a, nil } @@ -555,7 +555,7 @@ func _1598955122_add_mentionsDownSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1598955122_add_mentions.down.sql", size: 0, mode: os.FileMode(0664), modTime: time.Unix(1604073469, 0)} + info := bindataFileInfo{name: "1598955122_add_mentions.down.sql", size: 0, mode: os.FileMode(0644), modTime: time.Unix(1604483964, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55}} return a, nil } @@ -575,7 +575,7 @@ func _1598955122_add_mentionsUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1598955122_add_mentions.up.sql", size: 52, mode: os.FileMode(0664), modTime: time.Unix(1604073469, 0)} + info := bindataFileInfo{name: "1598955122_add_mentions.up.sql", size: 52, mode: os.FileMode(0644), modTime: time.Unix(1604483964, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x8d, 0x22, 0x17, 0x92, 0xd2, 0x11, 0x4e, 0x7, 0x93, 0x9a, 0x55, 0xfd, 0xb, 0x97, 0xc4, 0x63, 0x6a, 0x81, 0x97, 0xcd, 0xb2, 0xf8, 0x4b, 0x5f, 0x3c, 0xfa, 0x3a, 0x38, 0x53, 0x10, 0xed, 0x9d}} return a, nil } @@ -595,7 +595,7 @@ func _1599641390_add_emoji_reactions_indexDownSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1599641390_add_emoji_reactions_index.down.sql", size: 67, mode: os.FileMode(0664), modTime: time.Unix(1604073469, 0)} + info := bindataFileInfo{name: "1599641390_add_emoji_reactions_index.down.sql", size: 67, mode: os.FileMode(0644), modTime: time.Unix(1604483964, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x89, 0x39, 0x0, 0x51, 0x5b, 0x48, 0xc3, 0xf3, 0x6a, 0x96, 0xf1, 0xd2, 0xa6, 0x60, 0xa8, 0x68, 0x21, 0xb5, 0xa0, 0x11, 0x11, 0x99, 0xde, 0xad, 0xa6, 0xa7, 0x56, 0xc1, 0xb2, 0xa6, 0x63, 0xe4}} return a, nil } @@ -615,7 +615,7 @@ func _1599641390_add_emoji_reactions_indexUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1599641390_add_emoji_reactions_index.up.sql", size: 126, mode: os.FileMode(0664), modTime: time.Unix(1604073469, 0)} + info := bindataFileInfo{name: "1599641390_add_emoji_reactions_index.up.sql", size: 126, mode: os.FileMode(0644), modTime: time.Unix(1604483964, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xf9, 0xd8, 0xdc, 0xa7, 0xb, 0x92, 0x7a, 0x61, 0x37, 0x24, 0x1c, 0x77, 0x5e, 0xe, 0x7e, 0xfc, 0x9f, 0x98, 0x7b, 0x65, 0xe7, 0xf9, 0x71, 0x57, 0x89, 0x2d, 0x90, 0x1b, 0xf6, 0x5e, 0x37, 0xe8}} return a, nil } @@ -635,7 +635,7 @@ func _1599720851_add_seen_index_remove_long_messagesDownSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1599720851_add_seen_index_remove_long_messages.down.sql", size: 96, mode: os.FileMode(0664), modTime: time.Unix(1604073469, 0)} + info := bindataFileInfo{name: "1599720851_add_seen_index_remove_long_messages.down.sql", size: 96, mode: os.FileMode(0644), modTime: time.Unix(1604483964, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x6f, 0x80, 0x18, 0xaf, 0xf9, 0x83, 0xd6, 0xcb, 0xa1, 0xc1, 0xf1, 0xf6, 0x32, 0x11, 0xd2, 0x72, 0xef, 0x74, 0x83, 0x53, 0x3a, 0xc4, 0x77, 0x6, 0x66, 0xa0, 0xe3, 0x5a, 0x4d, 0x1b, 0x30, 0x6}} return a, nil } @@ -655,7 +655,7 @@ func _1599720851_add_seen_index_remove_long_messagesUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1599720851_add_seen_index_remove_long_messages.up.sql", size: 150, mode: os.FileMode(0664), modTime: time.Unix(1604073469, 0)} + info := bindataFileInfo{name: "1599720851_add_seen_index_remove_long_messages.up.sql", size: 150, mode: os.FileMode(0644), modTime: time.Unix(1604483964, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x24, 0x1c, 0xc4, 0x78, 0x91, 0xc7, 0xeb, 0xfe, 0xc8, 0xa0, 0xd8, 0x13, 0x27, 0x97, 0xc8, 0x96, 0x56, 0x97, 0x33, 0x2c, 0x1e, 0x16, 0x8a, 0xd3, 0x49, 0x99, 0x3, 0xe9, 0xbb, 0xc4, 0x5, 0x3c}} return a, nil } @@ -675,7 +675,7 @@ func _1603198582_add_profile_chat_fieldUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1603198582_add_profile_chat_field.up.sql", size: 45, mode: os.FileMode(0644), modTime: time.Unix(1604087530, 0)} + info := bindataFileInfo{name: "1603198582_add_profile_chat_field.up.sql", size: 45, mode: os.FileMode(0644), modTime: time.Unix(1604483964, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xaa, 0xca, 0xe, 0x46, 0xa0, 0x9, 0x9d, 0x47, 0x57, 0xe9, 0xfb, 0x17, 0xeb, 0x9c, 0xf6, 0xb8, 0x1d, 0xe9, 0xd, 0x0, 0xd5, 0xe5, 0xd8, 0x9e, 0x60, 0xa, 0xbf, 0x32, 0x2c, 0x52, 0x7f, 0x6a}} return a, nil } @@ -695,7 +695,7 @@ func _1603816533_add_linksDownSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1603816533_add_links.down.sql", size: 0, mode: os.FileMode(0644), modTime: time.Unix(1604087530, 0)} + info := bindataFileInfo{name: "1603816533_add_links.down.sql", size: 0, mode: os.FileMode(0644), modTime: time.Unix(1604483964, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55}} return a, nil } @@ -715,7 +715,7 @@ func _1603816533_add_linksUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1603816533_add_links.up.sql", size: 48, mode: os.FileMode(0644), modTime: time.Unix(1604087530, 0)} + info := bindataFileInfo{name: "1603816533_add_links.up.sql", size: 48, mode: os.FileMode(0644), modTime: time.Unix(1604483964, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xc9, 0x24, 0xd6, 0x1d, 0xa, 0x83, 0x1e, 0x4d, 0xf, 0xae, 0x4d, 0x8c, 0x51, 0x32, 0xa8, 0x37, 0xb0, 0x14, 0xfb, 0x32, 0x34, 0xc8, 0xc, 0x4e, 0x5b, 0xc5, 0x15, 0x65, 0x73, 0x0, 0x0, 0x1d}} return a, nil } @@ -735,7 +735,7 @@ func docGo() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "doc.go", size: 850, mode: os.FileMode(0664), modTime: time.Unix(1604073469, 0)} + info := bindataFileInfo{name: "doc.go", size: 850, mode: os.FileMode(0644), modTime: time.Unix(1604483964, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xa0, 0xcc, 0x41, 0xe1, 0x61, 0x12, 0x97, 0xe, 0x36, 0x8c, 0xa7, 0x9e, 0xe0, 0x6e, 0x59, 0x9e, 0xee, 0xd5, 0x4a, 0xcf, 0x1e, 0x60, 0xd6, 0xc3, 0x3a, 0xc9, 0x6c, 0xf2, 0x86, 0x5a, 0xb4, 0x1e}} return a, nil } @@ -831,71 +831,43 @@ func AssetNames() []string { // _bindata is a table, holding each asset generator, mapped to its name. var _bindata = map[string]func() (*asset, error){ - "000001_init.down.db.sql": _000001_initDownDbSql, - - "000001_init.up.db.sql": _000001_initUpDbSql, - - "000002_add_last_ens_clock_value.down.sql": _000002_add_last_ens_clock_valueDownSql, - - "000002_add_last_ens_clock_value.up.sql": _000002_add_last_ens_clock_valueUpSql, - - "1586358095_add_replace.down.sql": _1586358095_add_replaceDownSql, - - "1586358095_add_replace.up.sql": _1586358095_add_replaceUpSql, - - "1588665364_add_image_data.down.sql": _1588665364_add_image_dataDownSql, - - "1588665364_add_image_data.up.sql": _1588665364_add_image_dataUpSql, - - "1589365189_add_pow_target.down.sql": _1589365189_add_pow_targetDownSql, - - "1589365189_add_pow_target.up.sql": _1589365189_add_pow_targetUpSql, - - "1591277220_add_index_messages.down.sql": _1591277220_add_index_messagesDownSql, - - "1591277220_add_index_messages.up.sql": _1591277220_add_index_messagesUpSql, - + "000001_init.down.db.sql": _000001_initDownDbSql, + "000001_init.up.db.sql": _000001_initUpDbSql, + "000002_add_last_ens_clock_value.down.sql": _000002_add_last_ens_clock_valueDownSql, + "000002_add_last_ens_clock_value.up.sql": _000002_add_last_ens_clock_valueUpSql, + "1586358095_add_replace.down.sql": _1586358095_add_replaceDownSql, + "1586358095_add_replace.up.sql": _1586358095_add_replaceUpSql, + "1588665364_add_image_data.down.sql": _1588665364_add_image_dataDownSql, + "1588665364_add_image_data.up.sql": _1588665364_add_image_dataUpSql, + "1589365189_add_pow_target.down.sql": _1589365189_add_pow_targetDownSql, + "1589365189_add_pow_target.up.sql": _1589365189_add_pow_targetUpSql, + "1591277220_add_index_messages.down.sql": _1591277220_add_index_messagesDownSql, + "1591277220_add_index_messages.up.sql": _1591277220_add_index_messagesUpSql, "1593087212_add_mute_chat_and_raw_message_fields.down.sql": _1593087212_add_mute_chat_and_raw_message_fieldsDownSql, - - "1593087212_add_mute_chat_and_raw_message_fields.up.sql": _1593087212_add_mute_chat_and_raw_message_fieldsUpSql, - - "1595862781_add_audio_data.down.sql": _1595862781_add_audio_dataDownSql, - - "1595862781_add_audio_data.up.sql": _1595862781_add_audio_dataUpSql, - - "1595865249_create_emoji_reactions_table.down.sql": _1595865249_create_emoji_reactions_tableDownSql, - - "1595865249_create_emoji_reactions_table.up.sql": _1595865249_create_emoji_reactions_tableUpSql, - - "1596805115_create_group_chat_invitations_table.down.sql": _1596805115_create_group_chat_invitations_tableDownSql, - - "1596805115_create_group_chat_invitations_table.up.sql": _1596805115_create_group_chat_invitations_tableUpSql, - - "1597322655_add_invitation_admin_chat_field.up.sql": _1597322655_add_invitation_admin_chat_fieldUpSql, - - "1597757544_add_nickname.up.sql": _1597757544_add_nicknameUpSql, - - "1598955122_add_mentions.down.sql": _1598955122_add_mentionsDownSql, - - "1598955122_add_mentions.up.sql": _1598955122_add_mentionsUpSql, - - "1599641390_add_emoji_reactions_index.down.sql": _1599641390_add_emoji_reactions_indexDownSql, - - "1599641390_add_emoji_reactions_index.up.sql": _1599641390_add_emoji_reactions_indexUpSql, - - "1599720851_add_seen_index_remove_long_messages.down.sql": _1599720851_add_seen_index_remove_long_messagesDownSql, - - "1599720851_add_seen_index_remove_long_messages.up.sql": _1599720851_add_seen_index_remove_long_messagesUpSql, - - "1603198582_add_profile_chat_field.up.sql": _1603198582_add_profile_chat_fieldUpSql, - - "1603816533_add_links.down.sql": _1603816533_add_linksDownSql, - - "1603816533_add_links.up.sql": _1603816533_add_linksUpSql, - - "doc.go": docGo, + "1593087212_add_mute_chat_and_raw_message_fields.up.sql": _1593087212_add_mute_chat_and_raw_message_fieldsUpSql, + "1595862781_add_audio_data.down.sql": _1595862781_add_audio_dataDownSql, + "1595862781_add_audio_data.up.sql": _1595862781_add_audio_dataUpSql, + "1595865249_create_emoji_reactions_table.down.sql": _1595865249_create_emoji_reactions_tableDownSql, + "1595865249_create_emoji_reactions_table.up.sql": _1595865249_create_emoji_reactions_tableUpSql, + "1596805115_create_group_chat_invitations_table.down.sql": _1596805115_create_group_chat_invitations_tableDownSql, + "1596805115_create_group_chat_invitations_table.up.sql": _1596805115_create_group_chat_invitations_tableUpSql, + "1597322655_add_invitation_admin_chat_field.up.sql": _1597322655_add_invitation_admin_chat_fieldUpSql, + "1597757544_add_nickname.up.sql": _1597757544_add_nicknameUpSql, + "1598955122_add_mentions.down.sql": _1598955122_add_mentionsDownSql, + "1598955122_add_mentions.up.sql": _1598955122_add_mentionsUpSql, + "1599641390_add_emoji_reactions_index.down.sql": _1599641390_add_emoji_reactions_indexDownSql, + "1599641390_add_emoji_reactions_index.up.sql": _1599641390_add_emoji_reactions_indexUpSql, + "1599720851_add_seen_index_remove_long_messages.down.sql": _1599720851_add_seen_index_remove_long_messagesDownSql, + "1599720851_add_seen_index_remove_long_messages.up.sql": _1599720851_add_seen_index_remove_long_messagesUpSql, + "1603198582_add_profile_chat_field.up.sql": _1603198582_add_profile_chat_fieldUpSql, + "1603816533_add_links.down.sql": _1603816533_add_linksDownSql, + "1603816533_add_links.up.sql": _1603816533_add_linksUpSql, + "doc.go": docGo, } +// AssetDebug is true if the assets were built with the debug flag enabled. +const AssetDebug = false + // AssetDir returns the file names below a certain // directory embedded in the file by go-bindata. // For example if you run go-bindata on data/... and data contains the @@ -937,38 +909,38 @@ type bintree struct { } var _bintree = &bintree{nil, map[string]*bintree{ - "000001_init.down.db.sql": &bintree{_000001_initDownDbSql, map[string]*bintree{}}, - "000001_init.up.db.sql": &bintree{_000001_initUpDbSql, map[string]*bintree{}}, - "000002_add_last_ens_clock_value.down.sql": &bintree{_000002_add_last_ens_clock_valueDownSql, map[string]*bintree{}}, - "000002_add_last_ens_clock_value.up.sql": &bintree{_000002_add_last_ens_clock_valueUpSql, map[string]*bintree{}}, - "1586358095_add_replace.down.sql": &bintree{_1586358095_add_replaceDownSql, map[string]*bintree{}}, - "1586358095_add_replace.up.sql": &bintree{_1586358095_add_replaceUpSql, map[string]*bintree{}}, - "1588665364_add_image_data.down.sql": &bintree{_1588665364_add_image_dataDownSql, map[string]*bintree{}}, - "1588665364_add_image_data.up.sql": &bintree{_1588665364_add_image_dataUpSql, map[string]*bintree{}}, - "1589365189_add_pow_target.down.sql": &bintree{_1589365189_add_pow_targetDownSql, map[string]*bintree{}}, - "1589365189_add_pow_target.up.sql": &bintree{_1589365189_add_pow_targetUpSql, map[string]*bintree{}}, - "1591277220_add_index_messages.down.sql": &bintree{_1591277220_add_index_messagesDownSql, map[string]*bintree{}}, - "1591277220_add_index_messages.up.sql": &bintree{_1591277220_add_index_messagesUpSql, map[string]*bintree{}}, - "1593087212_add_mute_chat_and_raw_message_fields.down.sql": &bintree{_1593087212_add_mute_chat_and_raw_message_fieldsDownSql, map[string]*bintree{}}, - "1593087212_add_mute_chat_and_raw_message_fields.up.sql": &bintree{_1593087212_add_mute_chat_and_raw_message_fieldsUpSql, map[string]*bintree{}}, - "1595862781_add_audio_data.down.sql": &bintree{_1595862781_add_audio_dataDownSql, map[string]*bintree{}}, - "1595862781_add_audio_data.up.sql": &bintree{_1595862781_add_audio_dataUpSql, map[string]*bintree{}}, - "1595865249_create_emoji_reactions_table.down.sql": &bintree{_1595865249_create_emoji_reactions_tableDownSql, map[string]*bintree{}}, - "1595865249_create_emoji_reactions_table.up.sql": &bintree{_1595865249_create_emoji_reactions_tableUpSql, map[string]*bintree{}}, - "1596805115_create_group_chat_invitations_table.down.sql": &bintree{_1596805115_create_group_chat_invitations_tableDownSql, map[string]*bintree{}}, - "1596805115_create_group_chat_invitations_table.up.sql": &bintree{_1596805115_create_group_chat_invitations_tableUpSql, map[string]*bintree{}}, - "1597322655_add_invitation_admin_chat_field.up.sql": &bintree{_1597322655_add_invitation_admin_chat_fieldUpSql, map[string]*bintree{}}, - "1597757544_add_nickname.up.sql": &bintree{_1597757544_add_nicknameUpSql, map[string]*bintree{}}, - "1598955122_add_mentions.down.sql": &bintree{_1598955122_add_mentionsDownSql, map[string]*bintree{}}, - "1598955122_add_mentions.up.sql": &bintree{_1598955122_add_mentionsUpSql, map[string]*bintree{}}, - "1599641390_add_emoji_reactions_index.down.sql": &bintree{_1599641390_add_emoji_reactions_indexDownSql, map[string]*bintree{}}, - "1599641390_add_emoji_reactions_index.up.sql": &bintree{_1599641390_add_emoji_reactions_indexUpSql, map[string]*bintree{}}, - "1599720851_add_seen_index_remove_long_messages.down.sql": &bintree{_1599720851_add_seen_index_remove_long_messagesDownSql, map[string]*bintree{}}, - "1599720851_add_seen_index_remove_long_messages.up.sql": &bintree{_1599720851_add_seen_index_remove_long_messagesUpSql, map[string]*bintree{}}, - "1603198582_add_profile_chat_field.up.sql": &bintree{_1603198582_add_profile_chat_fieldUpSql, map[string]*bintree{}}, - "1603816533_add_links.down.sql": &bintree{_1603816533_add_linksDownSql, map[string]*bintree{}}, - "1603816533_add_links.up.sql": &bintree{_1603816533_add_linksUpSql, map[string]*bintree{}}, - "doc.go": &bintree{docGo, map[string]*bintree{}}, + "000001_init.down.db.sql": {_000001_initDownDbSql, map[string]*bintree{}}, + "000001_init.up.db.sql": {_000001_initUpDbSql, map[string]*bintree{}}, + "000002_add_last_ens_clock_value.down.sql": {_000002_add_last_ens_clock_valueDownSql, map[string]*bintree{}}, + "000002_add_last_ens_clock_value.up.sql": {_000002_add_last_ens_clock_valueUpSql, map[string]*bintree{}}, + "1586358095_add_replace.down.sql": {_1586358095_add_replaceDownSql, map[string]*bintree{}}, + "1586358095_add_replace.up.sql": {_1586358095_add_replaceUpSql, map[string]*bintree{}}, + "1588665364_add_image_data.down.sql": {_1588665364_add_image_dataDownSql, map[string]*bintree{}}, + "1588665364_add_image_data.up.sql": {_1588665364_add_image_dataUpSql, map[string]*bintree{}}, + "1589365189_add_pow_target.down.sql": {_1589365189_add_pow_targetDownSql, map[string]*bintree{}}, + "1589365189_add_pow_target.up.sql": {_1589365189_add_pow_targetUpSql, map[string]*bintree{}}, + "1591277220_add_index_messages.down.sql": {_1591277220_add_index_messagesDownSql, map[string]*bintree{}}, + "1591277220_add_index_messages.up.sql": {_1591277220_add_index_messagesUpSql, map[string]*bintree{}}, + "1593087212_add_mute_chat_and_raw_message_fields.down.sql": {_1593087212_add_mute_chat_and_raw_message_fieldsDownSql, map[string]*bintree{}}, + "1593087212_add_mute_chat_and_raw_message_fields.up.sql": {_1593087212_add_mute_chat_and_raw_message_fieldsUpSql, map[string]*bintree{}}, + "1595862781_add_audio_data.down.sql": {_1595862781_add_audio_dataDownSql, map[string]*bintree{}}, + "1595862781_add_audio_data.up.sql": {_1595862781_add_audio_dataUpSql, map[string]*bintree{}}, + "1595865249_create_emoji_reactions_table.down.sql": {_1595865249_create_emoji_reactions_tableDownSql, map[string]*bintree{}}, + "1595865249_create_emoji_reactions_table.up.sql": {_1595865249_create_emoji_reactions_tableUpSql, map[string]*bintree{}}, + "1596805115_create_group_chat_invitations_table.down.sql": {_1596805115_create_group_chat_invitations_tableDownSql, map[string]*bintree{}}, + "1596805115_create_group_chat_invitations_table.up.sql": {_1596805115_create_group_chat_invitations_tableUpSql, map[string]*bintree{}}, + "1597322655_add_invitation_admin_chat_field.up.sql": {_1597322655_add_invitation_admin_chat_fieldUpSql, map[string]*bintree{}}, + "1597757544_add_nickname.up.sql": {_1597757544_add_nicknameUpSql, map[string]*bintree{}}, + "1598955122_add_mentions.down.sql": {_1598955122_add_mentionsDownSql, map[string]*bintree{}}, + "1598955122_add_mentions.up.sql": {_1598955122_add_mentionsUpSql, map[string]*bintree{}}, + "1599641390_add_emoji_reactions_index.down.sql": {_1599641390_add_emoji_reactions_indexDownSql, map[string]*bintree{}}, + "1599641390_add_emoji_reactions_index.up.sql": {_1599641390_add_emoji_reactions_indexUpSql, map[string]*bintree{}}, + "1599720851_add_seen_index_remove_long_messages.down.sql": {_1599720851_add_seen_index_remove_long_messagesDownSql, map[string]*bintree{}}, + "1599720851_add_seen_index_remove_long_messages.up.sql": {_1599720851_add_seen_index_remove_long_messagesUpSql, map[string]*bintree{}}, + "1603198582_add_profile_chat_field.up.sql": {_1603198582_add_profile_chat_fieldUpSql, map[string]*bintree{}}, + "1603816533_add_links.down.sql": {_1603816533_add_linksDownSql, map[string]*bintree{}}, + "1603816533_add_links.up.sql": {_1603816533_add_linksUpSql, map[string]*bintree{}}, + "doc.go": {docGo, map[string]*bintree{}}, }} // RestoreAsset restores an asset under the given directory. diff --git a/protocol/persistence.go b/protocol/persistence.go index a67cc8527..7205d1b03 100644 --- a/protocol/persistence.go +++ b/protocol/persistence.go @@ -11,6 +11,7 @@ import ( "github.com/status-im/status-go/eth-node/crypto" "github.com/status-im/status-go/protocol/common" + "github.com/status-im/status-go/protocol/protobuf" ) var ( @@ -478,7 +479,7 @@ func (db sqlitePersistence) SaveRawMessage(message *common.RawMessage) error { resend_automatically, recipients, skip_encryption, - send_push_notification, + send_push_notification, payload ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, @@ -512,7 +513,7 @@ func (db sqlitePersistence) RawMessageByID(id string) (*common.RawMessage, error resend_automatically, recipients, skip_encryption, - send_push_notification, + send_push_notification, payload FROM raw_messages @@ -553,6 +554,60 @@ func (db sqlitePersistence) RawMessageByID(id string) (*common.RawMessage, error return message, nil } +func (db sqlitePersistence) RawMessagesIDsByType(t protobuf.ApplicationMetadataMessage_Type) ([]string, error) { + ids := []string{} + + rows, err := db.db.Query(` + SELECT + id + FROM + raw_messages + WHERE + message_type = ?`, + t) + if err != nil { + return ids, err + } + defer rows.Close() + + for rows.Next() { + var id string + if err := rows.Scan(&id); err != nil { + return ids, err + } + ids = append(ids, id) + } + + return ids, nil +} + +func (db sqlitePersistence) ExpiredEmojiReactionsIDs(maxSendCount int) ([]string, error) { + ids := []string{} + + rows, err := db.db.Query(` + SELECT + id + FROM + raw_messages + WHERE + message_type = ? AND sent = ? AND send_count <= ?`, + protobuf.ApplicationMetadataMessage_EMOJI_REACTION, false, maxSendCount) + if err != nil { + return ids, err + } + defer rows.Close() + + for rows.Next() { + var id string + if err := rows.Scan(&id); err != nil { + return ids, err + } + ids = append(ids, id) + } + + return ids, nil +} + func (db sqlitePersistence) SaveContact(contact *Contact, tx *sql.Tx) (err error) { if tx == nil { tx, err = db.db.BeginTx(context.Background(), &sql.TxOptions{}) diff --git a/protocol/persistence_test.go b/protocol/persistence_test.go index 5d84a1f2e..7fb39aeb5 100644 --- a/protocol/persistence_test.go +++ b/protocol/persistence_test.go @@ -378,6 +378,77 @@ func TestUpdateMessageOutgoingStatus(t *testing.T) { require.Equal(t, "new-status", m.OutgoingStatus) } +func TestMessagesIDsByType(t *testing.T) { + db, err := openTestDB() + require.NoError(t, err) + p := sqlitePersistence{db: db} + + ids, err := p.RawMessagesIDsByType(protobuf.ApplicationMetadataMessage_CHAT_MESSAGE) + require.NoError(t, err) + require.Empty(t, ids) + + err = p.SaveRawMessage(minimalRawMessage("chat-message-id", protobuf.ApplicationMetadataMessage_CHAT_MESSAGE)) + require.NoError(t, err) + ids, err = p.RawMessagesIDsByType(protobuf.ApplicationMetadataMessage_CHAT_MESSAGE) + require.NoError(t, err) + require.Equal(t, 1, len(ids)) + require.Equal(t, "chat-message-id", ids[0]) + + ids, err = p.RawMessagesIDsByType(protobuf.ApplicationMetadataMessage_EMOJI_REACTION) + require.NoError(t, err) + require.Empty(t, ids) + + err = p.SaveRawMessage(minimalRawMessage("emoji-message-id", protobuf.ApplicationMetadataMessage_EMOJI_REACTION)) + require.NoError(t, err) + ids, err = p.RawMessagesIDsByType(protobuf.ApplicationMetadataMessage_EMOJI_REACTION) + require.NoError(t, err) + require.Equal(t, 1, len(ids)) + require.Equal(t, "emoji-message-id", ids[0]) +} + +func TestExpiredEmojiReactionsIDs(t *testing.T) { + db, err := openTestDB() + require.NoError(t, err) + p := sqlitePersistence{db: db} + + ids, err := p.ExpiredEmojiReactionsIDs(emojiResendMaxCount) + require.NoError(t, err) + require.Empty(t, ids) + + //save expired chat message + rawChatMessage := minimalRawMessage("chat-message-id", protobuf.ApplicationMetadataMessage_CHAT_MESSAGE) + rawChatMessage.Sent = false + err = p.SaveRawMessage(rawChatMessage) + require.NoError(t, err) + + //make sure it doesn't apper in an expired emoji reactions list + ids, err = p.ExpiredEmojiReactionsIDs(emojiResendMaxCount) + require.NoError(t, err) + require.Empty(t, ids) + + //save expired emoji message + rawEmojiReaction := minimalRawMessage("emoji-message-id", protobuf.ApplicationMetadataMessage_EMOJI_REACTION) + rawEmojiReaction.Sent = false + err = p.SaveRawMessage(rawEmojiReaction) + require.NoError(t, err) + + //make sure it appered in expired emoji reactions list + ids, err = p.ExpiredEmojiReactionsIDs(emojiResendMaxCount) + require.NoError(t, err) + require.Equal(t, 1, len(ids)) + + //save non-expired emoji reaction + rawEmojiReaction2 := minimalRawMessage("emoji-message-id2", protobuf.ApplicationMetadataMessage_EMOJI_REACTION) + rawEmojiReaction2.Sent = true + err = p.SaveRawMessage(rawEmojiReaction2) + require.NoError(t, err) + + //make sure it didn't appear in expired emoji reactions list + ids, err = p.ExpiredEmojiReactionsIDs(emojiResendMaxCount) + require.NoError(t, err) + require.Equal(t, 1, len(ids)) +} + func TestPersistenceEmojiReactions(t *testing.T) { db, err := openTestDB() require.NoError(t, err) @@ -496,6 +567,14 @@ func insertMinimalMessage(p sqlitePersistence, id string) error { }}) } +func minimalRawMessage(id string, messageType protobuf.ApplicationMetadataMessage_Type) *common.RawMessage { + return &common.RawMessage{ + ID: id, + LocalChatID: "test-chat", + MessageType: messageType, + } +} + // Regression test making sure that if audio_duration_ms is null, no error is thrown func TestMessagesAudioDurationMsNull(t *testing.T) { db, err := openTestDB() diff --git a/protocol/transport/transport.go b/protocol/transport/transport.go index de15705bd..b96a431b9 100644 --- a/protocol/transport/transport.go +++ b/protocol/transport/transport.go @@ -39,4 +39,6 @@ type Transport interface { LoadKeyFilters(*ecdsa.PrivateKey) (*Filter, error) ProcessNegotiatedSecret(secret types.NegotiatedSecret) (*Filter, error) RetrieveRawAll() (map[Filter][]*types.Message, error) + + SetEnvelopeEventsHandler(handler EnvelopeEventsHandler) error } diff --git a/protocol/transport/waku/waku_service.go b/protocol/transport/waku/waku_service.go index 1e81c6b99..813ff90d4 100644 --- a/protocol/transport/waku/waku_service.go +++ b/protocol/transport/waku/waku_service.go @@ -383,3 +383,11 @@ func (a *Transport) waitForRequestCompleted(ctx context.Context, requestID []byt } } } + +func (a *Transport) SetEnvelopeEventsHandler(handler transport.EnvelopeEventsHandler) error { + if a.envelopesMonitor == nil { + return errors.New("Current transport has no envelopes monitor") + } + a.envelopesMonitor.handler = handler + return nil +} diff --git a/protocol/transport/whisper/whisper_service.go b/protocol/transport/whisper/whisper_service.go index 4959918bf..5bf249488 100644 --- a/protocol/transport/whisper/whisper_service.go +++ b/protocol/transport/whisper/whisper_service.go @@ -438,3 +438,11 @@ func (a *Transport) waitForRequestCompleted(ctx context.Context, requestID []byt } } } + +func (a *Transport) SetEnvelopeEventsHandler(handler transport.EnvelopeEventsHandler) error { + if a.envelopesMonitor == nil { + return errors.New("Current transport has no envelopes monitor") + } + a.envelopesMonitor.handler = handler + return nil +}