Merge branch 'feature/emoji-reactions' into develop

This commit is contained in:
Andrea Maria Piana 2020-07-30 21:30:38 +02:00
commit 14e426f39f
No known key found for this signature in database
GPG Key ID: AA6CCA6DE0E06424
110 changed files with 7584 additions and 1646 deletions

View File

@ -262,7 +262,7 @@ test-unit: UNIT_TEST_PACKAGES = $(shell go list ./... | \
grep -v /t/benchmarks | \
grep -v /transactions/fake )
test-unit: ##@tests Run unit and integration tests
go test -v -failfast $(UNIT_TEST_PACKAGES) $(gotest_extraflags)
go test -v -timeout 30m -failfast $(UNIT_TEST_PACKAGES) $(gotest_extraflags)
cd ./waku && go test -v -failfast ./... $(gotest_extraflags)
test-unit-race: gotest_extraflags=-race

View File

@ -1 +1 @@
0.56.3
0.56.4

View File

@ -337,7 +337,7 @@ func _0008_add_push_notificationsUpSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "0008_add_push_notifications.up.sql", size: 349, mode: os.FileMode(0644), modTime: time.Unix(1595832401, 0)}
info := bindataFileInfo{name: "0008_add_push_notifications.up.sql", size: 349, mode: os.FileMode(0644), modTime: time.Unix(1595840384, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x5a, 0x0, 0xbf, 0xd0, 0xdd, 0xcd, 0x73, 0xe0, 0x7c, 0x56, 0xef, 0xdc, 0x57, 0x61, 0x94, 0x64, 0x70, 0xb9, 0xfa, 0xa1, 0x2a, 0x36, 0xc, 0x2f, 0xf8, 0x95, 0xa, 0x57, 0x3e, 0x7a, 0xd7, 0x12}}
return a, nil
}

15
go.mod
View File

@ -17,9 +17,11 @@ require (
github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 // indirect
github.com/go-playground/universal-translator v0.17.0 // indirect
github.com/golang-migrate/migrate/v4 v4.8.0 // indirect
github.com/golang/groupcache v0.0.0-20191027212112-611e8accdfc9 // indirect
github.com/golang/mock v1.4.1
github.com/golang/protobuf v1.3.4
github.com/google/uuid v1.1.1
github.com/gorilla/mux v1.7.3 // indirect
github.com/jinzhu/copier v0.0.0-20190924061706-b57f9002281a
github.com/karalabe/usb v0.0.0-20191104083709-911d15fe12a9 // indirect
github.com/kilic/bls12-381 v0.0.0-20200607163746-32e1441c8a9f
@ -28,12 +30,19 @@ require (
github.com/libp2p/go-libp2p v0.4.2 // indirect
github.com/libp2p/go-libp2p-core v0.2.4
github.com/lucasb-eyer/go-colorful v1.0.3
github.com/mattn/go-colorable v0.1.4 // indirect
github.com/mattn/go-isatty v0.0.10 // indirect
github.com/mattn/go-pointer v0.0.0-20190911064623-a0a44394634f
github.com/mattn/go-runewidth v0.0.6 // indirect
github.com/mattn/go-sqlite3 v1.12.0 // indirect
github.com/multiformats/go-multiaddr v0.1.1
github.com/multiformats/go-multibase v0.0.1
github.com/multiformats/go-varint v0.0.5
github.com/mutecomm/go-sqlcipher v0.0.0-20190227152316-55dbde17881f
github.com/okzk/sdnotify v0.0.0-20180710141335-d9becc38acbd
github.com/olekukonko/tablewriter v0.0.2 // indirect
github.com/onsi/ginkgo v1.10.3 // indirect
github.com/onsi/gomega v1.7.1 // indirect
github.com/pborman/uuid v1.2.0
github.com/pkg/errors v0.9.1
github.com/prometheus/client_golang v1.5.0
@ -53,10 +62,16 @@ require (
github.com/tsenart/tb v0.0.0-20181025101425-0d2499c8b6e9
github.com/vacp2p/mvds v0.0.23
github.com/wealdtech/go-ens/v3 v3.3.0
go.uber.org/multierr v1.4.0 // indirect
go.uber.org/zap v1.13.0
golang.org/x/crypto v0.0.0-20191122220453-ac88ee75c92c
golang.org/x/net v0.0.0-20191119073136-fc4aabc6c914 // indirect
golang.org/x/time v0.0.0-20191024005414-555d28b269f0 // indirect
golang.org/x/tools v0.0.0-20200211045251-2de505fc5306 // indirect
google.golang.org/genproto v0.0.0-20191115221424-83cc0476cb11 // indirect
google.golang.org/grpc v1.25.1 // indirect
gopkg.in/go-playground/assert.v1 v1.2.1 // indirect
gopkg.in/go-playground/validator.v9 v9.31.0
gopkg.in/natefinch/lumberjack.v2 v2.0.0
gopkg.in/yaml.v2 v2.2.6 // indirect
)

39
go.sum
View File

@ -63,6 +63,7 @@ github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtE
github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs=
github.com/cenkalti/backoff/v3 v3.2.2 h1:cfUAAO3yvKMYKPrvhDuHSwQnhZNk/RMHKdZqKTxfm6M=
github.com/cenkalti/backoff/v3 v3.2.2/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk=
github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s=
github.com/cespare/cp v1.1.1 h1:nCb6ZLdB7NRaqsm91JtQTAme2SKJzXVsdPIPkyJr1MU=
@ -136,6 +137,8 @@ github.com/elastic/gosigar v0.0.0-20180330100440-37f05ff46ffa/go.mod h1:cdorVVzy
github.com/elastic/gosigar v0.10.4 h1:6jfw75dsoflhBMRdO6QPzQUgLqUYTsQQQRkkcsHsuPo=
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/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=
github.com/fatih/color v1.3.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
@ -183,6 +186,8 @@ github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekf
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6 h1:ZgQEtGgCBiWRM39fZuwSd1LwSqqSW0hOdXCYYDX0R3I=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191027212112-611e8accdfc9 h1:uHTyIjqVhYRhLbJ8nIiOJHkEZZ+5YoOsAbD3sk82NiE=
github.com/golang/groupcache v0.0.0-20191027212112-611e8accdfc9/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.4.1 h1:ocYkMQY5RrXTYgXl7ICpV0IXwlEQGwKIsery4gyXa1U=
@ -219,6 +224,8 @@ github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/mux v1.7.1 h1:Dw4jY2nghMMRsh1ol8dv1axHkDwMQK2DHerMNJsIpJU=
github.com/gorilla/mux v1.7.1/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/mux v1.7.3 h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw=
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM=
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
@ -431,21 +438,30 @@ github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaO
github.com/mattn/go-colorable v0.1.0/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.1 h1:G1f5SKeVxmagw/IyvzvtZE4Gybcc4Tr1tf7I8z0XgOg=
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA=
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-isatty v0.0.0-20180830101745-3fb116b82035/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.5 h1:tHXDdz1cpzGaovsTB+TVB8q90WEokoVmfMqoVcrLUgw=
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.7 h1:UvyT9uN+3r7yLEYSlJsbQGdsaB/a0DlgWP3pql6iwOc=
github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.10 h1:qxFzApOv4WsAL965uUPIsXzAKCZxN2p9UqdhFS4ZW10=
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
github.com/mattn/go-pointer v0.0.0-20190911064623-a0a44394634f h1:QTRRO+ozoYgT3CQRIzNVYJRU3DB8HRnkZv6mr4ISmMA=
github.com/mattn/go-pointer v0.0.0-20190911064623-a0a44394634f/go.mod h1:2zXcozF6qYGgmsG+SeTZz3oAbFLdD3OWqnUbNvJZAlc=
github.com/mattn/go-runewidth v0.0.3 h1:a+kO+98RDGEfo6asOGMmpodZq4FNtnGP54yps8BzLR4=
github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-runewidth v0.0.4 h1:2BvfKmzob6Bmd4YsL0zygOqfdFnK7GR4QL06Do4/p7Y=
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-runewidth v0.0.6 h1:V2iyH+aX9C5fsYCpK60U8BYIvmhqxuOL3JZcqc1NB7k=
github.com/mattn/go-runewidth v0.0.6/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/mattn/go-sqlite3 v1.10.0 h1:jbhqpg7tQe4SupckyijYiy0mJJ/pRyHvXf7JdWK860o=
github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/mattn/go-sqlite3 v1.12.0 h1:u/x3mp++qUxvYfulZ4HKOvVO0JWhk7HtE8lWhbGz/Do=
github.com/mattn/go-sqlite3 v1.12.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
@ -514,13 +530,19 @@ github.com/olekukonko/tablewriter v0.0.0-20170128050532-febf2d34b54a h1:m6hB6Gkm
github.com/olekukonko/tablewriter v0.0.0-20170128050532-febf2d34b54a/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
github.com/olekukonko/tablewriter v0.0.1 h1:b3iUnf1v+ppJiOfNX4yxxqfWKMQPZR5yoh8urCTFX88=
github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
github.com/olekukonko/tablewriter v0.0.2 h1:sq53g+DWf0J6/ceFUHpQ0nAEb6WgM++fq16MZ91cS6o=
github.com/olekukonko/tablewriter v0.0.2/go.mod h1:rSAaSIOAGT9odnlyGlUfAJaoc5w2fSBUmeGDbRWPxyQ=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.8.0 h1:VkHVNpR4iVnU8XQR6DBm8BqYjN7CRzw+xKUbVVbbW9w=
github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.10.3 h1:OoxbjfXVZyod1fmWYhI7SEyaD8B00ynP3T+D5GiyHOY=
github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.5.0 h1:izbySO9zDPmjJ8rDjLvkA2zJHIo+HkYXHnf7eN7SSyo=
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.7.1 h1:K0jcRCwNQM3vFGh1ppMtDh/+7ApJrjldlX8fA0jDTLQ=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/opencontainers/go-digest v1.0.0-rc1 h1:WzifXhOVOEOuFYOJAW6aQqW0TooG2iki3E3Ii+WN7gQ=
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI=
@ -708,6 +730,8 @@ go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/multierr v1.3.0 h1:sFPn2GLc3poCkfrpIXGhBD2X0CMIo4Q/zSULXrj/+uc=
go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
go.uber.org/multierr v1.4.0 h1:f3WCSC2KzAcBXGATIxAB1E2XuCpNU255wNKZ505qi3E=
go.uber.org/multierr v1.4.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4=
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
@ -760,6 +784,8 @@ golang.org/x/net v0.0.0-20190424112056-4829fb13d2c6/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191119073136-fc4aabc6c914 h1:MlY3mEfbnWGmUi4rtHOtNnnnN4UJRGSyLPx+DXA5Sq4=
golang.org/x/net v0.0.0-20191119073136-fc4aabc6c914/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@ -790,6 +816,7 @@ golang.org/x/sys v0.0.0-20190426135247-a129542de9ae/go.mod h1:h1NjWce9XRLGQEsW7w
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-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=
golang.org/x/sys v0.0.0-20191025090151-53bf42e6b339/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191113165036-4c7a9d0fe056 h1:dHtDnRWQtSx0Hjq9kvKFpBh9uPPKfQN70NZZmvssGwk=
@ -804,6 +831,8 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 h1:SvFZT6jyqRaOeXpc5h/JSfZenJ2O330aBsf7JfSUXmQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@ -815,6 +844,7 @@ golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190425222832-ad9eeb80039a/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
@ -840,10 +870,16 @@ google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRn
google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb h1:i1Ppqkc3WQXikh8bXiwHqAN5Rv3/qDCcRk0/Otx73BY=
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
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/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=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
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=
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=
gopkg.in/check.v1 v1.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
@ -880,11 +916,14 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.5 h1:ymVxjfMaHvXD8RqPRmzHHsB3VvucivSkIAvJFDI5O3c=
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.6 h1:97YCGUei5WVbkKfogoJQsLwUJ17cWvpLrgNvlcbxikE=
gopkg.in/yaml.v2 v2.2.6/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
modernc.org/b v1.0.0/go.mod h1:uZWcZfRj1BpYzfN9JTerzlNUnnPsV9O2ZA8JsRcubNg=

View File

@ -219,15 +219,19 @@ func (c *Chat) NextClockAndTimestamp(timesource TimeSource) (uint64, uint64) {
func (c *Chat) UpdateFromMessage(message *Message, timesource TimeSource) error {
c.Timestamp = int64(timesource.GetCurrentTime())
if c.LastClockValue <= message.Clock {
higherClock := c.LastClockValue <= message.Clock
// If the clock is higher, or last message is nil, we set the message
if higherClock || c.LastMessage == nil {
jsonMessage, err := json.Marshal(message)
if err != nil {
return err
}
c.LastClockValue = message.Clock
c.LastMessage = jsonMessage
}
// If the clock is higher we set the clock
if higherClock {
c.LastClockValue = message.Clock
}
return nil
}

View File

@ -70,3 +70,34 @@ func (s *ChatTestSuite) TestValidateChat() {
}
}
func (s *ChatTestSuite) TestUpdateFromMessage() {
// Base case, clock is higher
message := &Message{}
chat := &Chat{}
message.Clock = 1
s.Require().NoError(chat.UpdateFromMessage(message, &testTimeSource{}))
s.Require().NotNil(chat.LastMessage)
s.Require().Equal(uint64(1), chat.LastClockValue)
// Clock is lower and lastMessage is not nil
message = &Message{}
lastMessage := []byte("test")
chat = &Chat{LastClockValue: 2, LastMessage: lastMessage}
message.Clock = 1
s.Require().NoError(chat.UpdateFromMessage(message, &testTimeSource{}))
s.Require().Equal(lastMessage, chat.LastMessage)
s.Require().Equal(uint64(2), chat.LastClockValue)
// Clock is lower and lastMessage is nil
message = &Message{}
chat = &Chat{LastClockValue: 2}
message.Clock = 1
s.Require().NoError(chat.UpdateFromMessage(message, &testTimeSource{}))
s.Require().NotNil(chat.LastMessage)
s.Require().Equal(uint64(2), chat.LastClockValue)
}

View File

@ -0,0 +1,22 @@
package common
import (
"crypto/ecdsa"
"github.com/golang/protobuf/proto"
"github.com/status-im/status-go/protocol/protobuf"
)
// ChatEntity is anything that is sendable in a chat.
// Currently it encompass a Message and EmojiReaction.
type ChatEntity interface {
proto.Message
GetChatId() string
GetMessageType() protobuf.MessageType
GetSigPubKey() *ecdsa.PublicKey
GetProtobuf() proto.Message
SetMessageType(messageType protobuf.MessageType)
}

View File

@ -263,14 +263,24 @@ func (p *MessageProcessor) SendPairInstallation(
// All the events in a group are encoded and added to the payload
func (p *MessageProcessor) EncodeMembershipUpdate(
group *v1protocol.Group,
chatMessage *protobuf.ChatMessage,
chatEntity ChatEntity,
) ([]byte, error) {
message := v1protocol.MembershipUpdateMessage{
ChatID: group.ChatID(),
Events: group.Events(),
Message: chatMessage,
ChatID: group.ChatID(),
Events: group.Events(),
}
if chatEntity != nil {
chatEntityProtobuf := chatEntity.GetProtobuf()
switch chatEntityProtobuf := chatEntityProtobuf.(type) {
case *protobuf.ChatMessage:
message.Message = chatEntityProtobuf
case *protobuf.EmojiReaction:
message.EmojiReaction = chatEntityProtobuf
}
}
encodedMessage, err := v1protocol.EncodeMembershipUpdateMessage(message)
if err != nil {
return nil, errors.Wrap(err, "failed to encode membership update message")

View File

@ -44,7 +44,7 @@ func (s *MessageProcessorSuite) SetupTest() {
Text: "abc123",
ChatId: "testing-adamb",
ContentType: protobuf.ChatMessage_TEXT_PLAIN,
MessageType: protobuf.ChatMessage_PUBLIC_GROUP,
MessageType: protobuf.MessageType_PUBLIC_GROUP,
Clock: 154593077368201,
Timestamp: 1545930773682,
}
@ -129,7 +129,7 @@ func (s *MessageProcessorSuite) TestHandleDecodedMessagesWrapped() {
s.Require().Equal(1, len(decodedMessages))
s.Require().Equal(&authorKey.PublicKey, decodedMessages[0].SigPubKey())
s.Require().Equal(v1protocol.MessageID(&authorKey.PublicKey, wrappedPayload), decodedMessages[0].ID)
parsedMessage := decodedMessages[0].ParsedMessage.(protobuf.ChatMessage)
parsedMessage := decodedMessages[0].ParsedMessage.Interface().(protobuf.ChatMessage)
s.Require().Equal(encodedPayload, decodedMessages[0].DecryptedPayload)
s.Require().True(proto.Equal(&s.testMessage, &parsedMessage))
s.Require().Equal(protobuf.ApplicationMetadataMessage_CHAT_MESSAGE, decodedMessages[0].Type)
@ -167,7 +167,7 @@ func (s *MessageProcessorSuite) TestHandleDecodedMessagesDatasync() {
s.Require().Equal(&authorKey.PublicKey, decodedMessages[0].SigPubKey())
s.Require().Equal(v1protocol.MessageID(&authorKey.PublicKey, wrappedPayload), decodedMessages[0].ID)
s.Require().Equal(encodedPayload, decodedMessages[0].DecryptedPayload)
parsedMessage := decodedMessages[0].ParsedMessage.(protobuf.ChatMessage)
parsedMessage := decodedMessages[0].ParsedMessage.Interface().(protobuf.ChatMessage)
s.Require().True(proto.Equal(&s.testMessage, &parsedMessage))
s.Require().Equal(protobuf.ApplicationMetadataMessage_CHAT_MESSAGE, decodedMessages[0].Type)
}
@ -235,7 +235,7 @@ func (s *MessageProcessorSuite) TestHandleDecodedMessagesDatasyncEncrypted() {
s.Require().Equal(&authorKey.PublicKey, decodedMessages[0].SigPubKey())
s.Require().Equal(v1protocol.MessageID(&authorKey.PublicKey, wrappedPayload), decodedMessages[0].ID)
s.Require().Equal(encodedPayload, decodedMessages[0].DecryptedPayload)
parsedMessage := decodedMessages[0].ParsedMessage.(protobuf.ChatMessage)
parsedMessage := decodedMessages[0].ParsedMessage.Interface().(protobuf.ChatMessage)
s.Require().True(proto.Equal(&s.testMessage, &parsedMessage))
s.Require().Equal(protobuf.ApplicationMetadataMessage_CHAT_MESSAGE, decodedMessages[0].Type)
}

View File

@ -0,0 +1,78 @@
package protocol
import (
"crypto/ecdsa"
"encoding/json"
"fmt"
"github.com/golang/protobuf/proto"
"github.com/status-im/status-go/eth-node/crypto"
"github.com/status-im/status-go/eth-node/types"
"github.com/status-im/status-go/protocol/protobuf"
)
// EmojiReaction represents an emoji reaction from a user in the application layer, used for persistence, querying and
// signaling
type EmojiReaction struct {
protobuf.EmojiReaction
// From is a public key of the author of the emoji reaction.
From string `json:"from,omitempty"`
// SigPubKey is the ecdsa encoded public key of the emoji reaction author
SigPubKey *ecdsa.PublicKey `json:"-"`
// LocalChatID is the chatID of the local chat (one-to-one are not symmetric)
LocalChatID string `json:"localChatId"`
}
// ID is the Keccak256() contatenation of From-MessageID-EmojiType
func (e EmojiReaction) ID() string {
return types.EncodeHex(crypto.Keccak256([]byte(fmt.Sprintf("%s%s%d", e.From, e.MessageId, e.Type))))
}
// GetSigPubKey returns an ecdsa encoded public key
// this function is required to implement the ChatEntity interface
func (e EmojiReaction) GetSigPubKey() *ecdsa.PublicKey {
return e.SigPubKey
}
// GetProtoBuf returns the struct's embedded protobuf struct
// this function is required to implement the ChatEntity interface
func (e EmojiReaction) GetProtobuf() proto.Message {
return &e.EmojiReaction
}
// SetMessageType a setter for the MessageType field
// this function is required to implement the ChatEntity interface
func (e *EmojiReaction) SetMessageType(messageType protobuf.MessageType) {
e.MessageType = messageType
}
func (e EmojiReaction) MarshalJSON() ([]byte, error) {
item := struct {
ID string `json:"id"`
Clock uint64 `json:"clock,omitempty"`
ChatID string `json:"chatId,omitempty"`
LocalChatID string `json:"localChatId,omitempty"`
From string `json:"from"`
MessageID string `json:"messageId,omitempty"`
MessageType protobuf.MessageType `json:"messageType,omitempty"`
Retracted bool `json:"retracted,omitempty"`
EmojiID protobuf.EmojiReaction_Type `json:"emojiId,omitempty"`
}{
ID: e.ID(),
Clock: e.Clock,
ChatID: e.ChatId,
LocalChatID: e.LocalChatID,
From: e.From,
MessageID: e.MessageId,
MessageType: e.MessageType,
Retracted: e.Retracted,
EmojiID: e.Type,
}
return json.Marshal(item)
}

View File

@ -60,7 +60,7 @@ func eventToSystemMessage(e v1protocol.MembershipUpdateEvent, translations map[p
ChatMessage: protobuf.ChatMessage{
ChatId: e.ChatID,
Text: text,
MessageType: protobuf.ChatMessage_SYSTEM_MESSAGE_PRIVATE_GROUP,
MessageType: protobuf.MessageType_SYSTEM_MESSAGE_PRIVATE_GROUP,
ContentType: protobuf.ChatMessage_SYSTEM_MESSAGE_CONTENT_PRIVATE_GROUP,
Clock: e.ClockValue,
Timestamp: timestamp,

View File

@ -10,6 +10,7 @@ import (
"unicode"
"unicode/utf8"
"github.com/golang/protobuf/proto"
"github.com/status-im/markdown"
"github.com/status-im/status-go/protocol/protobuf"
@ -148,7 +149,7 @@ func (m *Message) MarshalJSON() ([]byte, error) {
CommandParameters *CommandParameters `json:"commandParameters"`
Timestamp uint64 `json:"timestamp"`
ContentType protobuf.ChatMessage_ContentType `json:"contentType"`
MessageType protobuf.ChatMessage_MessageType `json:"messageType"`
MessageType protobuf.MessageType `json:"messageType"`
}{
ID: m.ID,
WhisperTimestamp: m.WhisperTimestamp,
@ -175,7 +176,6 @@ func (m *Message) MarshalJSON() ([]byte, error) {
MessageType: m.MessageType,
CommandParameters: m.CommandParameters,
}
if sticker := m.GetSticker(); sticker != nil {
item.Sticker = &StickerAlias{
Pack: sticker.Pack,
@ -333,3 +333,21 @@ func getAudioMessageMIME(i *protobuf.AudioMessage) (string, error) {
return "", errors.New("audio format not supported")
}
// GetSigPubKey returns an ecdsa encoded public key
// this function is required to implement the ChatEntity interface
func (m Message) GetSigPubKey() *ecdsa.PublicKey {
return m.SigPubKey
}
// GetProtoBuf returns the struct's embedded protobuf struct
// this function is required to implement the ChatEntity interface
func (m *Message) GetProtobuf() proto.Message {
return &m.ChatMessage
}
// SetMessageType a setter for the MessageType field
// this function is required to implement the ChatEntity interface
func (m *Message) SetMessageType(messageType protobuf.MessageType) {
m.MessageType = messageType
}

View File

@ -110,6 +110,8 @@ func (m *MessageHandler) HandleMembershipUpdate(messageState *ReceivedMessageSta
if message.Message != nil {
messageState.CurrentMessageState.Message = *message.Message
return m.HandleChatMessage(messageState)
} else if message.EmojiReaction != nil {
return m.HandleEmojiReaction(messageState, *message.EmojiReaction)
}
return nil
@ -126,7 +128,7 @@ func (m *MessageHandler) handleCommandMessage(state *ReceivedMessageState, messa
if err := message.PrepareContent(); err != nil {
return fmt.Errorf("failed to prepare content: %v", err)
}
chat, err := m.matchMessage(message, state.AllChats, state.Timesource)
chat, err := m.matchChatEntity(message, state.AllChats, state.Timesource)
if err != nil {
return err
}
@ -312,9 +314,9 @@ func (m *MessageHandler) HandleChatMessage(state *ReceivedMessageState) error {
if err != nil {
return fmt.Errorf("failed to prepare message content: %v", err)
}
chat, err := m.matchMessage(receivedMessage, state.AllChats, state.Timesource)
chat, err := m.matchChatEntity(receivedMessage, state.AllChats, state.Timesource)
if err != nil {
return err // matchMessage returns a descriptive error message
return err // matchChatEntity returns a descriptive error message
}
// If deleted-at is greater, ignore message
@ -359,9 +361,7 @@ func (m *MessageHandler) HandleChatMessage(state *ReceivedMessageState) error {
}
// Add to response
if receivedMessage != nil {
state.Response.Messages = append(state.Response.Messages, receivedMessage)
}
state.Response.Messages = append(state.Response.Messages, receivedMessage)
return nil
}
@ -377,7 +377,7 @@ func (m *MessageHandler) HandleRequestAddressForTransaction(messageState *Receiv
Timestamp: messageState.CurrentMessageState.WhisperTimestamp,
Text: "Request address for transaction",
ChatId: contactIDFromPublicKey(&m.identity.PublicKey),
MessageType: protobuf.ChatMessage_ONE_TO_ONE,
MessageType: protobuf.MessageType_ONE_TO_ONE,
ContentType: protobuf.ChatMessage_TRANSACTION_COMMAND,
},
CommandParameters: &CommandParameters{
@ -401,7 +401,7 @@ func (m *MessageHandler) HandleRequestTransaction(messageState *ReceivedMessageS
Timestamp: messageState.CurrentMessageState.WhisperTimestamp,
Text: "Request transaction",
ChatId: contactIDFromPublicKey(&m.identity.PublicKey),
MessageType: protobuf.ChatMessage_ONE_TO_ONE,
MessageType: protobuf.MessageType_ONE_TO_ONE,
ContentType: protobuf.ChatMessage_TRANSACTION_COMMAND,
},
CommandParameters: &CommandParameters{
@ -567,26 +567,26 @@ func (m *MessageHandler) HandleDeclineRequestTransaction(messageState *ReceivedM
return m.handleCommandMessage(messageState, oldMessage)
}
func (m *MessageHandler) matchMessage(message *Message, chats map[string]*Chat, timesource TimeSource) (*Chat, error) {
if message.SigPubKey == nil {
func (m *MessageHandler) matchChatEntity(chatEntity common.ChatEntity, chats map[string]*Chat, timesource TimeSource) (*Chat, error) {
if chatEntity.GetSigPubKey() == nil {
m.logger.Error("public key can't be empty")
return nil, errors.New("received a message with empty public key")
return nil, errors.New("received a chatEntity with empty public key")
}
switch {
case message.MessageType == protobuf.ChatMessage_PUBLIC_GROUP:
case chatEntity.GetMessageType() == protobuf.MessageType_PUBLIC_GROUP:
// For public messages, all outgoing and incoming messages have the same chatID
// equal to a public chat name.
chatID := message.ChatId
chatID := chatEntity.GetChatId()
chat := chats[chatID]
if chat == nil {
return nil, errors.New("received a public message from non-existing chat")
return nil, errors.New("received a public chatEntity from non-existing chat")
}
return chat, nil
case message.MessageType == protobuf.ChatMessage_ONE_TO_ONE && common.IsPubKeyEqual(message.SigPubKey, &m.identity.PublicKey):
case chatEntity.GetMessageType() == protobuf.MessageType_ONE_TO_ONE && common.IsPubKeyEqual(chatEntity.GetSigPubKey(), &m.identity.PublicKey):
// It's a private message coming from us so we rely on Message.ChatID
// If chat does not exist, it should be created to support multidevice synchronization.
chatID := message.ChatId
chatID := chatEntity.GetChatId()
chat := chats[chatID]
if chat == nil {
if len(chatID) != PubKeyStringLength {
@ -606,27 +606,27 @@ func (m *MessageHandler) matchMessage(message *Message, chats map[string]*Chat,
chat = &newChat
}
return chat, nil
case message.MessageType == protobuf.ChatMessage_ONE_TO_ONE:
// It's an incoming private message. ChatID is calculated from the signature.
case chatEntity.GetMessageType() == protobuf.MessageType_ONE_TO_ONE:
// It's an incoming private chatEntity. ChatID is calculated from the signature.
// If a chat does not exist, a new one is created and saved.
chatID := contactIDFromPublicKey(message.SigPubKey)
chatID := contactIDFromPublicKey(chatEntity.GetSigPubKey())
chat := chats[chatID]
if chat == nil {
// TODO: this should be a three-word name used in the mobile client
newChat := CreateOneToOneChat(chatID[:8], message.SigPubKey, timesource)
newChat := CreateOneToOneChat(chatID[:8], chatEntity.GetSigPubKey(), timesource)
chat = &newChat
}
return chat, nil
case message.MessageType == protobuf.ChatMessage_PRIVATE_GROUP:
// In the case of a group message, ChatID is the same for all messages belonging to a group.
case chatEntity.GetMessageType() == protobuf.MessageType_PRIVATE_GROUP:
// In the case of a group chatEntity, ChatID is the same for all messages belonging to a group.
// It needs to be verified if the signature public key belongs to the chat.
chatID := message.ChatId
chatID := chatEntity.GetChatId()
chat := chats[chatID]
if chat == nil {
return nil, errors.New("received group chat message for non-existing chat")
return nil, errors.New("received group chat chatEntity for non-existing chat")
}
theirKeyHex := contactIDFromPublicKey(message.SigPubKey)
theirKeyHex := contactIDFromPublicKey(chatEntity.GetSigPubKey())
myKeyHex := contactIDFromPublicKey(&m.identity.PublicKey)
var theyJoined bool
var iJoined bool
@ -669,3 +669,56 @@ func (m *MessageHandler) messageExists(messageID string, existingMessagesMap map
}
return false, nil
}
func (m *MessageHandler) HandleEmojiReaction(state *ReceivedMessageState, pbEmojiR protobuf.EmojiReaction) error {
logger := m.logger.With(zap.String("site", "HandleEmojiReaction"))
if err := ValidateReceivedEmojiReaction(&pbEmojiR, state.Timesource.GetCurrentTime()); err != nil {
logger.Error("invalid emoji reaction", zap.Error(err))
return err
}
from := state.CurrentMessageState.Contact.ID
emojiReaction := &EmojiReaction{
EmojiReaction: pbEmojiR,
From: from,
SigPubKey: state.CurrentMessageState.PublicKey,
}
existingEmoji, err := m.persistence.EmojiReactionByID(emojiReaction.ID())
if err != errRecordNotFound && err != nil {
return err
}
if existingEmoji != nil && existingEmoji.Clock >= pbEmojiR.Clock {
// this is not a valid emoji, ignoring
return nil
}
chat, err := m.matchChatEntity(emojiReaction, state.AllChats, state.Timesource)
if err != nil {
return err // matchChatEntity returns a descriptive error message
}
// Set local chat id
emojiReaction.LocalChatID = chat.ID
logger.Debug("Handling emoji reaction")
if chat.LastClockValue < pbEmojiR.Clock {
chat.LastClockValue = pbEmojiR.Clock
}
state.ModifiedChats[chat.ID] = true
state.AllChats[chat.ID] = chat
// save emoji reaction
err = m.persistence.SaveEmojiReaction(emojiReaction)
if err != nil {
return err
}
state.EmojiReactions[emojiReaction.ID()] = emojiReaction
return nil
}

View File

@ -172,15 +172,16 @@ func (db sqlitePersistence) tableUserMessagesScanAllFields(row scanner, message
}
message.Alias = alias.String
message.Identicon = identicon.String
if message.ContentType == protobuf.ChatMessage_STICKER {
switch message.ContentType {
case protobuf.ChatMessage_STICKER:
message.Payload = &protobuf.ChatMessage_Sticker{Sticker: sticker}
}
if message.ContentType == protobuf.ChatMessage_AUDIO {
message.Payload = &protobuf.ChatMessage_Audio{Audio: audio}
}
if message.ContentType == protobuf.ChatMessage_AUDIO {
message.Payload = &protobuf.ChatMessage_Audio{Audio: audio}
}
if message.ContentType == protobuf.ChatMessage_TRANSACTION_COMMAND {
case protobuf.ChatMessage_TRANSACTION_COMMAND:
message.CommandParameters = command
}
@ -407,6 +408,7 @@ func (db sqlitePersistence) MessagesByIDs(ids []string) ([]*Message, error) {
return nil, err
}
defer rows.Close()
var result []*Message
for rows.Next() {
var message Message
@ -488,6 +490,79 @@ func (db sqlitePersistence) MessageByChatID(chatID string, currCursor string, li
return result, newCursor, nil
}
// EmojiReactionsByChatID returns the emoji reactions for the queried messages, up to a maximum of 100, as it's a potentially unbound number.
// NOTE: This is not completely accurate, as the messages in the database might have change since the last call to `MessageByChatID`.
func (db sqlitePersistence) EmojiReactionsByChatID(chatID string, currCursor string, limit int) ([]*EmojiReaction, error) {
cursorWhere := ""
if currCursor != "" {
cursorWhere = "AND substr('0000000000000000000000000000000000000000000000000000000000000000' || m.clock_value, -64, 64) || m.id <= ?"
}
args := []interface{}{chatID, chatID}
if currCursor != "" {
args = append(args, currCursor)
}
args = append(args, limit)
// NOTE: We match against local_chat_id for security reasons.
// As a user could potentially send an emoji reaction for a one to
// one/group chat that has no access to.
// We also limit the number of emoji to a reasonable number (1000)
// for now, as we don't want the client to choke on this.
// The issue is that your own emoji might not be returned in such cases,
// allowing the user to react to a post multiple times.
// Jakubgs: Returning the whole list seems like a real overkill.
// This will get very heavy in threads that have loads of reactions on loads of messages.
// A more sensible response would just include a count and a bool telling you if you are in the list.
// nolint: gosec
query := fmt.Sprintf(`
SELECT
e.clock_value,
e.source,
e.emoji_id,
e.message_id,
e.chat_id,
e.local_chat_id,
e.retracted
FROM
emoji_reactions e
WHERE NOT(e.retracted)
AND
e.local_chat_id = ?
AND
e.message_id IN
(SELECT id FROM user_messages m WHERE NOT(m.hide) AND m.local_chat_id = ? %s
ORDER BY substr('0000000000000000000000000000000000000000000000000000000000000000' || m.clock_value, -64, 64) || m.id DESC LIMIT ?)
LIMIT 1000
`, cursorWhere)
rows, err := db.db.Query(
query,
args...,
)
if err != nil {
return nil, err
}
defer rows.Close()
var result []*EmojiReaction
for rows.Next() {
var emojiReaction EmojiReaction
err := rows.Scan(&emojiReaction.Clock,
&emojiReaction.From,
&emojiReaction.Type,
&emojiReaction.MessageId,
&emojiReaction.ChatId,
&emojiReaction.LocalChatID,
&emojiReaction.Retracted)
if err != nil {
return nil, err
}
result = append(result, &emojiReaction)
}
return result, nil
}
func (db sqlitePersistence) SaveMessages(messages []*Message) (err error) {
tx, err := db.db.BeginTx(context.Background(), &sql.TxOptions{})
if err != nil {
@ -704,3 +779,60 @@ func (db sqlitePersistence) BlockContact(contact *Contact) ([]*Chat, error) {
return chats, err
}
func (db sqlitePersistence) SaveEmojiReaction(emojiReaction *EmojiReaction) (err error) {
query := "INSERT INTO emoji_reactions(id,clock_value,source,emoji_id,message_id,chat_id,local_chat_id,retracted) VALUES (?,?,?,?,?,?,?,?)"
stmt, err := db.db.Prepare(query)
if err != nil {
return
}
_, err = stmt.Exec(
emojiReaction.ID(),
emojiReaction.Clock,
emojiReaction.From,
emojiReaction.Type,
emojiReaction.MessageId,
emojiReaction.ChatId,
emojiReaction.LocalChatID,
emojiReaction.Retracted,
)
return
}
func (db sqlitePersistence) EmojiReactionByID(id string) (*EmojiReaction, error) {
row := db.db.QueryRow(
`SELECT
clock_value,
source,
emoji_id,
message_id,
chat_id,
local_chat_id,
retracted
FROM
emoji_reactions
WHERE
emoji_reactions.id = ?
`, id)
emojiReaction := new(EmojiReaction)
err := row.Scan(&emojiReaction.Clock,
&emojiReaction.From,
&emojiReaction.Type,
&emojiReaction.MessageId,
&emojiReaction.ChatId,
&emojiReaction.LocalChatID,
&emojiReaction.Retracted,
)
switch err {
case sql.ErrNoRows:
return nil, errRecordNotFound
case nil:
return emojiReaction, nil
default:
return nil, err
}
}

View File

@ -167,19 +167,18 @@ func ValidateReceivedChatMessage(message *protobuf.ChatMessage, whisperTimestamp
return errors.New("chatId can't be empty")
}
if message.ContentType == protobuf.ChatMessage_UNKNOWN_CONTENT_TYPE {
return errors.New("unknown content type")
}
if message.ContentType == protobuf.ChatMessage_TRANSACTION_COMMAND {
return errors.New("can't receive request address for transaction from others")
}
if message.MessageType == protobuf.ChatMessage_UNKNOWN_MESSAGE_TYPE || message.MessageType == protobuf.ChatMessage_SYSTEM_MESSAGE_PRIVATE_GROUP {
if message.MessageType == protobuf.MessageType_UNKNOWN_MESSAGE_TYPE || message.MessageType == protobuf.MessageType_SYSTEM_MESSAGE_PRIVATE_GROUP {
return errors.New("unknown message type")
}
if message.ContentType == protobuf.ChatMessage_STICKER {
switch message.ContentType {
case protobuf.ChatMessage_UNKNOWN_CONTENT_TYPE:
return errors.New("unknown content type")
case protobuf.ChatMessage_TRANSACTION_COMMAND:
return errors.New("can't receive request address for transaction from others")
case protobuf.ChatMessage_STICKER:
if message.Payload == nil {
return errors.New("no sticker content")
}
@ -190,9 +189,8 @@ func ValidateReceivedChatMessage(message *protobuf.ChatMessage, whisperTimestamp
if len(sticker.Hash) == 0 {
return errors.New("sticker hash not set")
}
}
if message.ContentType == protobuf.ChatMessage_IMAGE {
case protobuf.ChatMessage_IMAGE:
if message.Payload == nil {
return errors.New("no image content")
}
@ -203,7 +201,6 @@ func ValidateReceivedChatMessage(message *protobuf.ChatMessage, whisperTimestamp
if len(image.Payload) == 0 {
return errors.New("image payload empty")
}
if image.Type == protobuf.ImageMessage_UNKNOWN_IMAGE_TYPE {
return errors.New("image type unknown")
}
@ -228,3 +225,27 @@ func ValidateReceivedChatMessage(message *protobuf.ChatMessage, whisperTimestamp
return nil
}
func ValidateReceivedEmojiReaction(emoji *protobuf.EmojiReaction, whisperTimestamp uint64) error {
if err := validateClockValue(emoji.Clock, whisperTimestamp); err != nil {
return err
}
if len(emoji.MessageId) == 0 {
return errors.New("message-id can't be empty")
}
if len(emoji.ChatId) == 0 {
return errors.New("chat-id can't be empty")
}
if emoji.Type == protobuf.EmojiReaction_UNKNOWN_EMOJI_REACTION_TYPE {
return errors.New("unknown emoji reaction type")
}
if emoji.MessageType == protobuf.MessageType_UNKNOWN_MESSAGE_TYPE {
return errors.New("unknown message type")
}
return nil
}

View File

@ -103,7 +103,7 @@ func (s *MessageValidatorSuite) TestValidatePlainTextMessage() {
Text: "some-text",
ResponseTo: "",
EnsName: "",
MessageType: protobuf.ChatMessage_ONE_TO_ONE,
MessageType: protobuf.MessageType_ONE_TO_ONE,
ContentType: protobuf.ChatMessage_TEXT_PLAIN,
},
},
@ -117,7 +117,7 @@ func (s *MessageValidatorSuite) TestValidatePlainTextMessage() {
Text: "some-text",
ResponseTo: "",
EnsName: "",
MessageType: protobuf.ChatMessage_ONE_TO_ONE,
MessageType: protobuf.MessageType_ONE_TO_ONE,
ContentType: protobuf.ChatMessage_TEXT_PLAIN,
},
},
@ -131,7 +131,7 @@ func (s *MessageValidatorSuite) TestValidatePlainTextMessage() {
Text: "some-text",
ResponseTo: "",
EnsName: "",
MessageType: protobuf.ChatMessage_ONE_TO_ONE,
MessageType: protobuf.MessageType_ONE_TO_ONE,
ContentType: protobuf.ChatMessage_TEXT_PLAIN,
},
},
@ -146,7 +146,7 @@ func (s *MessageValidatorSuite) TestValidatePlainTextMessage() {
Text: "some-text",
ResponseTo: "",
EnsName: "",
MessageType: protobuf.ChatMessage_ONE_TO_ONE,
MessageType: protobuf.MessageType_ONE_TO_ONE,
ContentType: protobuf.ChatMessage_TEXT_PLAIN,
},
},
@ -160,7 +160,7 @@ func (s *MessageValidatorSuite) TestValidatePlainTextMessage() {
Text: "some-text",
ResponseTo: "",
EnsName: "",
MessageType: protobuf.ChatMessage_ONE_TO_ONE,
MessageType: protobuf.MessageType_ONE_TO_ONE,
ContentType: protobuf.ChatMessage_TEXT_PLAIN,
},
},
@ -174,7 +174,7 @@ func (s *MessageValidatorSuite) TestValidatePlainTextMessage() {
Timestamp: 3,
ResponseTo: "",
EnsName: "",
MessageType: protobuf.ChatMessage_ONE_TO_ONE,
MessageType: protobuf.MessageType_ONE_TO_ONE,
ContentType: protobuf.ChatMessage_TEXT_PLAIN,
},
},
@ -189,7 +189,7 @@ func (s *MessageValidatorSuite) TestValidatePlainTextMessage() {
Timestamp: 3,
ResponseTo: "",
EnsName: "",
MessageType: protobuf.ChatMessage_ONE_TO_ONE,
MessageType: protobuf.MessageType_ONE_TO_ONE,
ContentType: protobuf.ChatMessage_TEXT_PLAIN,
},
},
@ -204,7 +204,7 @@ func (s *MessageValidatorSuite) TestValidatePlainTextMessage() {
Timestamp: 3,
ResponseTo: "",
EnsName: "",
MessageType: protobuf.ChatMessage_UNKNOWN_MESSAGE_TYPE,
MessageType: protobuf.MessageType_UNKNOWN_MESSAGE_TYPE,
ContentType: protobuf.ChatMessage_TEXT_PLAIN,
},
},
@ -219,7 +219,7 @@ func (s *MessageValidatorSuite) TestValidatePlainTextMessage() {
Timestamp: 3,
ResponseTo: "",
EnsName: "",
MessageType: protobuf.ChatMessage_ONE_TO_ONE,
MessageType: protobuf.MessageType_ONE_TO_ONE,
ContentType: protobuf.ChatMessage_UNKNOWN_CONTENT_TYPE,
},
},
@ -234,7 +234,7 @@ func (s *MessageValidatorSuite) TestValidatePlainTextMessage() {
Timestamp: 3,
ResponseTo: "",
EnsName: "",
MessageType: protobuf.ChatMessage_SYSTEM_MESSAGE_PRIVATE_GROUP,
MessageType: protobuf.MessageType_SYSTEM_MESSAGE_PRIVATE_GROUP,
ContentType: protobuf.ChatMessage_TEXT_PLAIN,
},
},
@ -249,7 +249,7 @@ func (s *MessageValidatorSuite) TestValidatePlainTextMessage() {
Timestamp: 3,
ResponseTo: "",
EnsName: "",
MessageType: protobuf.ChatMessage_ONE_TO_ONE,
MessageType: protobuf.MessageType_ONE_TO_ONE,
ContentType: protobuf.ChatMessage_TRANSACTION_COMMAND,
},
},
@ -264,7 +264,7 @@ func (s *MessageValidatorSuite) TestValidatePlainTextMessage() {
Timestamp: 3,
ResponseTo: "",
EnsName: "",
MessageType: protobuf.ChatMessage_ONE_TO_ONE,
MessageType: protobuf.MessageType_ONE_TO_ONE,
ContentType: protobuf.ChatMessage_EMOJI,
},
},
@ -279,7 +279,7 @@ func (s *MessageValidatorSuite) TestValidatePlainTextMessage() {
Timestamp: 3,
ResponseTo: "",
EnsName: "",
MessageType: protobuf.ChatMessage_ONE_TO_ONE,
MessageType: protobuf.MessageType_ONE_TO_ONE,
ContentType: protobuf.ChatMessage_EMOJI,
},
}
@ -301,7 +301,7 @@ func (s *MessageValidatorSuite) TestValidatePlainTextMessage() {
Hash: "some-hash",
},
},
MessageType: protobuf.ChatMessage_ONE_TO_ONE,
MessageType: protobuf.MessageType_ONE_TO_ONE,
ContentType: protobuf.ChatMessage_STICKER,
},
},
@ -321,7 +321,7 @@ func (s *MessageValidatorSuite) TestValidatePlainTextMessage() {
Pack: 1,
},
},
MessageType: protobuf.ChatMessage_ONE_TO_ONE,
MessageType: protobuf.MessageType_ONE_TO_ONE,
ContentType: protobuf.ChatMessage_STICKER,
},
},
@ -336,7 +336,7 @@ func (s *MessageValidatorSuite) TestValidatePlainTextMessage() {
Timestamp: 3,
ResponseTo: "",
EnsName: "",
MessageType: protobuf.ChatMessage_ONE_TO_ONE,
MessageType: protobuf.MessageType_ONE_TO_ONE,
ContentType: protobuf.ChatMessage_STICKER,
},
},
@ -357,7 +357,7 @@ func (s *MessageValidatorSuite) TestValidatePlainTextMessage() {
Payload: []byte("some-payload"),
},
},
MessageType: protobuf.ChatMessage_ONE_TO_ONE,
MessageType: protobuf.MessageType_ONE_TO_ONE,
ContentType: protobuf.ChatMessage_IMAGE,
},
},
@ -378,7 +378,7 @@ func (s *MessageValidatorSuite) TestValidatePlainTextMessage() {
Payload: []byte("some-payload"),
},
},
MessageType: protobuf.ChatMessage_ONE_TO_ONE,
MessageType: protobuf.MessageType_ONE_TO_ONE,
ContentType: protobuf.ChatMessage_STICKER,
},
},
@ -398,7 +398,7 @@ func (s *MessageValidatorSuite) TestValidatePlainTextMessage() {
Type: 1,
},
},
MessageType: protobuf.ChatMessage_ONE_TO_ONE,
MessageType: protobuf.MessageType_ONE_TO_ONE,
ContentType: protobuf.ChatMessage_IMAGE,
},
},
@ -419,7 +419,7 @@ func (s *MessageValidatorSuite) TestValidatePlainTextMessage() {
Payload: []byte("some-payload"),
},
},
MessageType: protobuf.ChatMessage_ONE_TO_ONE,
MessageType: protobuf.MessageType_ONE_TO_ONE,
ContentType: protobuf.ChatMessage_AUDIO,
},
},
@ -440,7 +440,7 @@ func (s *MessageValidatorSuite) TestValidatePlainTextMessage() {
Payload: []byte("some-payload"),
},
},
MessageType: protobuf.ChatMessage_ONE_TO_ONE,
MessageType: protobuf.MessageType_ONE_TO_ONE,
ContentType: protobuf.ChatMessage_STICKER,
},
},
@ -460,7 +460,7 @@ func (s *MessageValidatorSuite) TestValidatePlainTextMessage() {
Type: 1,
},
},
MessageType: protobuf.ChatMessage_ONE_TO_ONE,
MessageType: protobuf.MessageType_ONE_TO_ONE,
ContentType: protobuf.ChatMessage_AUDIO,
},
},
@ -477,3 +477,105 @@ func (s *MessageValidatorSuite) TestValidatePlainTextMessage() {
})
}
}
func (s *MessageValidatorSuite) TestValidateEmojiReaction() {
testCases := []struct {
Name string
Valid bool
WhisperTimestamp uint64
Message protobuf.EmojiReaction
}{
{
Name: "valid emoji reaction",
Valid: true,
WhisperTimestamp: 30,
Message: protobuf.EmojiReaction{
Clock: 30,
ChatId: "chat-id",
MessageId: "message-id",
MessageType: protobuf.MessageType_ONE_TO_ONE,
Type: protobuf.EmojiReaction_LOVE,
},
},
{
Name: "valid emoji retraction",
Valid: true,
WhisperTimestamp: 30,
Message: protobuf.EmojiReaction{
Clock: 30,
ChatId: "0.34",
MessageId: "message-id",
Type: protobuf.EmojiReaction_LOVE,
MessageType: protobuf.MessageType_ONE_TO_ONE,
Retracted: true,
},
},
{
Name: "missing chatID",
Valid: false,
WhisperTimestamp: 30,
Message: protobuf.EmojiReaction{
Clock: 30,
MessageId: "message-id",
MessageType: protobuf.MessageType_ONE_TO_ONE,
Type: protobuf.EmojiReaction_LOVE,
},
},
{
Name: "missing messageID",
Valid: false,
WhisperTimestamp: 30,
Message: protobuf.EmojiReaction{
Clock: 30,
ChatId: "chat-id",
MessageType: protobuf.MessageType_ONE_TO_ONE,
Type: protobuf.EmojiReaction_LOVE,
},
},
{
Name: "missing type",
Valid: false,
WhisperTimestamp: 30,
Message: protobuf.EmojiReaction{
Clock: 30,
ChatId: "chat-id",
MessageId: "message-id",
MessageType: protobuf.MessageType_ONE_TO_ONE,
},
},
{
Name: "missing message type",
Valid: false,
WhisperTimestamp: 30,
Message: protobuf.EmojiReaction{
Clock: 30,
ChatId: "chat-id",
MessageId: "message-id",
Type: protobuf.EmojiReaction_LOVE,
},
},
{
Name: "clock value too high",
Valid: false,
WhisperTimestamp: 30,
Message: protobuf.EmojiReaction{
Clock: 900000,
ChatId: "chat-id",
MessageId: "message-id",
MessageType: protobuf.MessageType_ONE_TO_ONE,
Type: protobuf.EmojiReaction_LOVE,
},
},
}
for _, tc := range testCases {
s.Run(tc.Name, func() {
err := ValidateReceivedEmojiReaction(&tc.Message, tc.WhisperTimestamp)
if tc.Valid {
s.Nil(err)
} else {
s.NotNil(err)
}
})
}
}

View File

@ -87,10 +87,11 @@ type RawResponse struct {
}
type MessengerResponse struct {
Chats []*Chat `json:"chats,omitempty"`
Messages []*Message `json:"messages,omitempty"`
Contacts []*Contact `json:"contacts,omitempty"`
Installations []*multidevice.Installation `json:"installations,omitempty"`
Chats []*Chat `json:"chats,omitempty"`
Messages []*Message `json:"messages,omitempty"`
Contacts []*Contact `json:"contacts,omitempty"`
Installations []*multidevice.Installation `json:"installations,omitempty"`
EmojiReactions []*EmojiReaction `json:"emojiReactions,omitempty"`
}
func (m *MessengerResponse) IsEmpty() bool {
@ -1409,7 +1410,6 @@ func (m *Messenger) SendChatMessage(ctx context.Context, message *Message) (*Mes
}
}
logger := m.logger.With(zap.String("site", "Send"), zap.String("chatID", message.ChatId))
var response MessengerResponse
// A valid added chat is required.
@ -1423,38 +1423,9 @@ func (m *Messenger) SendChatMessage(ctx context.Context, message *Message) (*Mes
return nil, err
}
var encodedMessage []byte
switch chat.ChatType {
case ChatTypeOneToOne:
logger.Debug("sending private message")
message.MessageType = protobuf.ChatMessage_ONE_TO_ONE
encodedMessage, err = proto.Marshal(message)
if err != nil {
return nil, err
}
case ChatTypePublic:
logger.Debug("sending public message", zap.String("chatName", chat.Name))
message.MessageType = protobuf.ChatMessage_PUBLIC_GROUP
encodedMessage, err = proto.Marshal(message)
if err != nil {
return nil, err
}
case ChatTypePrivateGroupChat:
message.MessageType = protobuf.ChatMessage_PRIVATE_GROUP
logger.Debug("sending group message", zap.String("chatName", chat.Name))
group, err := newProtocolGroupFromChat(chat)
if err != nil {
return nil, err
}
encodedMessage, err = m.processor.EncodeMembershipUpdate(group, &message.ChatMessage)
if err != nil {
return nil, err
}
default:
return nil, errors.New("chat type not supported")
encodedMessage, err := m.encodeChatEntity(chat, message)
if err != nil {
return nil, err
}
id, err := m.dispatchMessage(ctx, common.RawMessage{
@ -1805,6 +1776,9 @@ type ReceivedMessageState struct {
ModifiedInstallations map[string]bool
// Map of existing messages
ExistingMessagesMap map[string]bool
// EmojiReactions is a list of emoji reactions for the current batch
// indexed by from-message-id-emoji-type
EmojiReactions map[string]*EmojiReaction
// Response to the client
Response *MessengerResponse
// Timesource is a time source for clock values/timestamps.
@ -1822,6 +1796,7 @@ func (m *Messenger) handleRetrievedMessages(chatWithMessages map[transport.Filte
AllInstallations: m.allInstallations,
ModifiedInstallations: m.modifiedInstallations,
ExistingMessagesMap: make(map[string]bool),
EmojiReactions: make(map[string]*EmojiReaction),
Response: &MessengerResponse{},
Timesource: m.getTimesource(),
}
@ -1878,11 +1853,11 @@ func (m *Messenger) handleRetrievedMessages(chatWithMessages map[transport.Filte
if msg.ParsedMessage != nil {
logger.Debug("Handling parsed message")
switch msg.ParsedMessage.(type) {
switch msg.ParsedMessage.Interface().(type) {
case protobuf.MembershipUpdateMessage:
logger.Debug("Handling MembershipUpdateMessage")
rawMembershipUpdate := msg.ParsedMessage.(protobuf.MembershipUpdateMessage)
rawMembershipUpdate := msg.ParsedMessage.Interface().(protobuf.MembershipUpdateMessage)
err = m.handler.HandleMembershipUpdate(messageState, messageState.AllChats[rawMembershipUpdate.ChatId], rawMembershipUpdate, m.systemMessagesTranslations)
if err != nil {
@ -1892,18 +1867,19 @@ func (m *Messenger) handleRetrievedMessages(chatWithMessages map[transport.Filte
case protobuf.ChatMessage:
logger.Debug("Handling ChatMessage")
messageState.CurrentMessageState.Message = msg.ParsedMessage.(protobuf.ChatMessage)
messageState.CurrentMessageState.Message = msg.ParsedMessage.Interface().(protobuf.ChatMessage)
err = m.handler.HandleChatMessage(messageState)
if err != nil {
logger.Warn("failed to handle ChatMessage", zap.Error(err))
continue
}
case protobuf.PairInstallation:
if !common.IsPubKeyEqual(messageState.CurrentMessageState.PublicKey, &m.identity.PublicKey) {
logger.Warn("not coming from us, ignoring")
continue
}
p := msg.ParsedMessage.(protobuf.PairInstallation)
p := msg.ParsedMessage.Interface().(protobuf.PairInstallation)
logger.Debug("Handling PairInstallation", zap.Any("message", p))
err = m.handler.HandlePairInstallation(messageState, p)
if err != nil {
@ -1917,44 +1893,48 @@ func (m *Messenger) handleRetrievedMessages(chatWithMessages map[transport.Filte
continue
}
p := msg.ParsedMessage.(protobuf.SyncInstallationContact)
p := msg.ParsedMessage.Interface().(protobuf.SyncInstallationContact)
logger.Debug("Handling SyncInstallationContact", zap.Any("message", p))
err = m.handler.HandleSyncInstallationContact(messageState, p)
if err != nil {
logger.Warn("failed to handle SyncInstallationContact", zap.Error(err))
continue
}
case protobuf.SyncInstallationPublicChat:
if !common.IsPubKeyEqual(messageState.CurrentMessageState.PublicKey, &m.identity.PublicKey) {
logger.Warn("not coming from us, ignoring")
continue
}
p := msg.ParsedMessage.(protobuf.SyncInstallationPublicChat)
p := msg.ParsedMessage.Interface().(protobuf.SyncInstallationPublicChat)
logger.Debug("Handling SyncInstallationPublicChat", zap.Any("message", p))
err = m.handler.HandleSyncInstallationPublicChat(messageState, p)
if err != nil {
logger.Warn("failed to handle SyncInstallationPublicChat", zap.Error(err))
continue
}
case protobuf.RequestAddressForTransaction:
command := msg.ParsedMessage.(protobuf.RequestAddressForTransaction)
command := msg.ParsedMessage.Interface().(protobuf.RequestAddressForTransaction)
logger.Debug("Handling RequestAddressForTransaction", zap.Any("message", command))
err = m.handler.HandleRequestAddressForTransaction(messageState, command)
if err != nil {
logger.Warn("failed to handle RequestAddressForTransaction", zap.Error(err))
continue
}
case protobuf.SendTransaction:
command := msg.ParsedMessage.(protobuf.SendTransaction)
command := msg.ParsedMessage.Interface().(protobuf.SendTransaction)
logger.Debug("Handling SendTransaction", zap.Any("message", command))
err = m.handler.HandleSendTransaction(messageState, command)
if err != nil {
logger.Warn("failed to handle SendTransaction", zap.Error(err))
continue
}
case protobuf.AcceptRequestAddressForTransaction:
command := msg.ParsedMessage.(protobuf.AcceptRequestAddressForTransaction)
command := msg.ParsedMessage.Interface().(protobuf.AcceptRequestAddressForTransaction)
logger.Debug("Handling AcceptRequestAddressForTransaction")
err = m.handler.HandleAcceptRequestAddressForTransaction(messageState, command)
if err != nil {
@ -1963,7 +1943,7 @@ func (m *Messenger) handleRetrievedMessages(chatWithMessages map[transport.Filte
}
case protobuf.DeclineRequestAddressForTransaction:
command := msg.ParsedMessage.(protobuf.DeclineRequestAddressForTransaction)
command := msg.ParsedMessage.Interface().(protobuf.DeclineRequestAddressForTransaction)
logger.Debug("Handling DeclineRequestAddressForTransaction")
err = m.handler.HandleDeclineRequestAddressForTransaction(messageState, command)
if err != nil {
@ -1972,7 +1952,7 @@ func (m *Messenger) handleRetrievedMessages(chatWithMessages map[transport.Filte
}
case protobuf.DeclineRequestTransaction:
command := msg.ParsedMessage.(protobuf.DeclineRequestTransaction)
command := msg.ParsedMessage.Interface().(protobuf.DeclineRequestTransaction)
logger.Debug("Handling DeclineRequestTransaction")
err = m.handler.HandleDeclineRequestTransaction(messageState, command)
if err != nil {
@ -1981,18 +1961,17 @@ func (m *Messenger) handleRetrievedMessages(chatWithMessages map[transport.Filte
}
case protobuf.RequestTransaction:
command := msg.ParsedMessage.(protobuf.RequestTransaction)
command := msg.ParsedMessage.Interface().(protobuf.RequestTransaction)
logger.Debug("Handling RequestTransaction")
err = m.handler.HandleRequestTransaction(messageState, command)
if err != nil {
logger.Warn("failed to handle RequestTransaction", zap.Error(err))
continue
}
case protobuf.ContactUpdate:
logger.Debug("Handling ContactUpdate")
contactUpdate := msg.ParsedMessage.(protobuf.ContactUpdate)
contactUpdate := msg.ParsedMessage.Interface().(protobuf.ContactUpdate)
err = m.handler.HandleContactUpdate(messageState, contactUpdate)
if err != nil {
logger.Warn("failed to handle ContactUpdate", zap.Error(err))
@ -2004,7 +1983,7 @@ func (m *Messenger) handleRetrievedMessages(chatWithMessages map[transport.Filte
continue
}
logger.Debug("Handling PushNotificationQuery")
if err := m.pushNotificationServer.HandlePushNotificationQuery(publicKey, msg.ID, msg.ParsedMessage.(protobuf.PushNotificationQuery)); err != nil {
if err := m.pushNotificationServer.HandlePushNotificationQuery(publicKey, msg.ID, msg.ParsedMessage.Interface().(protobuf.PushNotificationQuery)); err != nil {
logger.Warn("failed to handle PushNotificationQuery", zap.Error(err))
}
// We continue in any case, no changes to messenger
@ -2015,7 +1994,7 @@ func (m *Messenger) handleRetrievedMessages(chatWithMessages map[transport.Filte
continue
}
logger.Debug("Handling PushNotificationRegistrationResponse")
if err := m.pushNotificationClient.HandlePushNotificationRegistrationResponse(publicKey, msg.ParsedMessage.(protobuf.PushNotificationRegistrationResponse)); err != nil {
if err := m.pushNotificationClient.HandlePushNotificationRegistrationResponse(publicKey, msg.ParsedMessage.Interface().(protobuf.PushNotificationRegistrationResponse)); err != nil {
logger.Warn("failed to handle PushNotificationRegistrationResponse", zap.Error(err))
}
// We continue in any case, no changes to messenger
@ -2026,7 +2005,7 @@ func (m *Messenger) handleRetrievedMessages(chatWithMessages map[transport.Filte
continue
}
logger.Debug("Handling PushNotificationResponse")
if err := m.pushNotificationClient.HandlePushNotificationResponse(publicKey, msg.ParsedMessage.(protobuf.PushNotificationResponse)); err != nil {
if err := m.pushNotificationClient.HandlePushNotificationResponse(publicKey, msg.ParsedMessage.Interface().(protobuf.PushNotificationResponse)); err != nil {
logger.Warn("failed to handle PushNotificationResponse", zap.Error(err))
}
// We continue in any case, no changes to messenger
@ -2038,7 +2017,7 @@ func (m *Messenger) handleRetrievedMessages(chatWithMessages map[transport.Filte
continue
}
logger.Debug("Handling PushNotificationQueryResponse")
if err := m.pushNotificationClient.HandlePushNotificationQueryResponse(publicKey, msg.ParsedMessage.(protobuf.PushNotificationQueryResponse)); err != nil {
if err := m.pushNotificationClient.HandlePushNotificationQueryResponse(publicKey, msg.ParsedMessage.Interface().(protobuf.PushNotificationQueryResponse)); err != nil {
logger.Warn("failed to handle PushNotificationQueryResponse", zap.Error(err))
}
// We continue in any case, no changes to messenger
@ -2050,11 +2029,18 @@ func (m *Messenger) handleRetrievedMessages(chatWithMessages map[transport.Filte
continue
}
logger.Debug("Handling PushNotificationRequest")
if err := m.pushNotificationServer.HandlePushNotificationRequest(publicKey, msg.ParsedMessage.(protobuf.PushNotificationRequest)); err != nil {
if err := m.pushNotificationServer.HandlePushNotificationRequest(publicKey, msg.ParsedMessage.Interface().(protobuf.PushNotificationRequest)); err != nil {
logger.Warn("failed to handle PushNotificationRequest", zap.Error(err))
}
// We continue in any case, no changes to messenger
continue
case protobuf.EmojiReaction:
logger.Debug("Handling EmojiReaction")
err = m.handler.HandleEmojiReaction(messageState, msg.ParsedMessage.Interface().(protobuf.EmojiReaction))
if err != nil {
logger.Warn("failed to handle EmojiReaction", zap.Error(err))
continue
}
default:
// Check if is an encrypted PushNotificationRegistration
@ -2064,14 +2050,14 @@ func (m *Messenger) handleRetrievedMessages(chatWithMessages map[transport.Filte
continue
}
logger.Debug("Handling PushNotificationRegistration")
if err := m.pushNotificationServer.HandlePushNotificationRegistration(publicKey, msg.ParsedMessage.([]byte)); err != nil {
if err := m.pushNotificationServer.HandlePushNotificationRegistration(publicKey, msg.ParsedMessage.Interface().([]byte)); err != nil {
logger.Warn("failed to handle PushNotificationRegistration", zap.Error(err))
}
// We continue in any case, no changes to messenger
continue
}
logger.Debug("message not handled", zap.Any("messageType", reflect.TypeOf(msg.ParsedMessage)))
logger.Debug("message not handled", zap.Any("messageType", reflect.TypeOf(msg.ParsedMessage.Interface())))
}
}
@ -2131,6 +2117,10 @@ func (m *Messenger) handleRetrievedMessages(chatWithMessages map[transport.Filte
}
}
for _, emojiReaction := range messageState.EmojiReactions {
messageState.Response.EmojiReactions = append(messageState.Response.EmojiReactions, emojiReaction)
}
if len(contactsToSave) > 0 {
err = m.persistence.SaveContacts(contactsToSave)
if err != nil {
@ -2381,7 +2371,7 @@ func (m *Messenger) RequestTransaction(ctx context.Context, chatID, value, contr
return nil, err
}
message.MessageType = protobuf.ChatMessage_ONE_TO_ONE
message.MessageType = protobuf.MessageType_ONE_TO_ONE
message.ContentType = protobuf.ChatMessage_TRANSACTION_COMMAND
message.Text = "Request transaction"
@ -2458,7 +2448,7 @@ func (m *Messenger) RequestAddressForTransaction(ctx context.Context, chatID, fr
return nil, err
}
message.MessageType = protobuf.ChatMessage_ONE_TO_ONE
message.MessageType = protobuf.MessageType_ONE_TO_ONE
message.ContentType = protobuf.ChatMessage_TRANSACTION_COMMAND
message.Text = "Request address for transaction"
@ -2892,7 +2882,7 @@ func (m *Messenger) SendTransaction(ctx context.Context, chatID, value, contract
return nil, err
}
message.MessageType = protobuf.ChatMessage_ONE_TO_ONE
message.MessageType = protobuf.MessageType_ONE_TO_ONE
message.ContentType = protobuf.ChatMessage_TRANSACTION_COMMAND
message.LocalChatID = chatID
@ -2993,7 +2983,7 @@ func (m *Messenger) ValidateTransactions(ctx context.Context, addresses []types.
}
}
message.MessageType = protobuf.ChatMessage_ONE_TO_ONE
message.MessageType = protobuf.MessageType_ONE_TO_ONE
message.ContentType = protobuf.ChatMessage_TRANSACTION_COMMAND
message.LocalChatID = chatID
message.OutgoingStatus = ""
@ -3235,3 +3225,161 @@ func generateAliasAndIdenticon(pk string) (string, string, error) {
return name, identicon, nil
}
func (m *Messenger) SendEmojiReaction(ctx context.Context, chatID, messageID string, emojiID protobuf.EmojiReaction_Type) (*MessengerResponse, error) {
m.mutex.Lock()
defer m.mutex.Unlock()
var response MessengerResponse
chat, ok := m.allChats[chatID]
if !ok {
return nil, ErrChatNotFound
}
clock, _ := chat.NextClockAndTimestamp(m.getTimesource())
emojiR := &EmojiReaction{
EmojiReaction: protobuf.EmojiReaction{
Clock: clock,
MessageId: messageID,
ChatId: chatID,
Type: emojiID,
},
LocalChatID: chatID,
From: types.EncodeHex(crypto.FromECDSAPub(&m.identity.PublicKey)),
}
encodedMessage, err := m.encodeChatEntity(chat, emojiR)
if err != nil {
return nil, err
}
_, err = m.dispatchMessage(ctx, common.RawMessage{
LocalChatID: chatID,
Payload: encodedMessage,
MessageType: protobuf.ApplicationMetadataMessage_EMOJI_REACTION,
// Don't resend using datasync, that would create quite a lot
// of traffic if clicking too eagelry
ResendAutomatically: false,
})
if err != nil {
return nil, err
}
response.EmojiReactions = []*EmojiReaction{emojiR}
response.Chats = []*Chat{chat}
err = m.persistence.SaveEmojiReaction(emojiR)
if err != nil {
return nil, err
}
return &response, nil
}
func (m *Messenger) EmojiReactionsByChatID(chatID string, cursor string, limit int) ([]*EmojiReaction, error) {
return m.persistence.EmojiReactionsByChatID(chatID, cursor, limit)
}
func (m *Messenger) SendEmojiReactionRetraction(ctx context.Context, emojiReactionID string) (*MessengerResponse, error) {
m.mutex.Lock()
defer m.mutex.Unlock()
emojiR, err := m.persistence.EmojiReactionByID(emojiReactionID)
if err != nil {
return nil, err
}
// Check that the sender is the key owner
pk := types.EncodeHex(crypto.FromECDSAPub(&m.identity.PublicKey))
if emojiR.From != pk {
return nil, errors.Errorf("identity mismatch, "+
"emoji reactions can only be retracted by the reaction sender, "+
"emoji reaction sent by '%s', current identity '%s'",
emojiR.From, pk,
)
}
// Get chat and clock
chat, ok := m.allChats[emojiR.GetChatId()]
if !ok {
return nil, ErrChatNotFound
}
clock, _ := chat.NextClockAndTimestamp(m.getTimesource())
// Update the relevant fields
emojiR.Clock = clock
emojiR.Retracted = true
encodedMessage, err := m.encodeChatEntity(chat, emojiR)
if err != nil {
return nil, err
}
// Send the marshalled EmojiReactionRetraction protobuf
_, err = m.dispatchMessage(ctx, common.RawMessage{
LocalChatID: emojiR.GetChatId(),
Payload: encodedMessage,
MessageType: protobuf.ApplicationMetadataMessage_EMOJI_REACTION,
// Don't resend using datasync, that would create quite a lot
// of traffic if clicking too eagelry
ResendAutomatically: false,
})
if err != nil {
return nil, err
}
// Update MessengerResponse
response := MessengerResponse{}
emojiR.Retracted = true
response.EmojiReactions = []*EmojiReaction{emojiR}
response.Chats = []*Chat{chat}
// Persist retraction state for emoji reaction
err = m.persistence.SaveEmojiReaction(emojiR)
if err != nil {
return nil, err
}
return &response, nil
}
func (m *Messenger) encodeChatEntity(chat *Chat, message common.ChatEntity) ([]byte, error) {
var encodedMessage []byte
var err error
l := m.logger.With(zap.String("site", "Send"), zap.String("chatID", chat.ID))
switch chat.ChatType {
case ChatTypeOneToOne:
l.Debug("sending private message")
message.SetMessageType(protobuf.MessageType_ONE_TO_ONE)
encodedMessage, err = proto.Marshal(message.GetProtobuf())
if err != nil {
return nil, err
}
case ChatTypePublic:
l.Debug("sending public message", zap.String("chatName", chat.Name))
message.SetMessageType(protobuf.MessageType_PUBLIC_GROUP)
encodedMessage, err = proto.Marshal(message.GetProtobuf())
if err != nil {
return nil, err
}
case ChatTypePrivateGroupChat:
message.SetMessageType(protobuf.MessageType_PRIVATE_GROUP)
l.Debug("sending group message", zap.String("chatName", chat.Name))
group, err := newProtocolGroupFromChat(chat)
if err != nil {
return nil, err
}
encodedMessage, err = m.processor.EncodeMembershipUpdate(group, message)
if err != nil {
return nil, err
}
default:
return nil, errors.New("chat type not supported")
}
return encodedMessage, nil
}

View File

@ -0,0 +1,220 @@
package protocol
import (
"context"
"crypto/ecdsa"
"io/ioutil"
"os"
"testing"
"github.com/google/uuid"
"github.com/stretchr/testify/suite"
"go.uber.org/zap"
gethbridge "github.com/status-im/status-go/eth-node/bridge/geth"
"github.com/status-im/status-go/eth-node/crypto"
"github.com/status-im/status-go/eth-node/types"
"github.com/status-im/status-go/protocol/protobuf"
"github.com/status-im/status-go/protocol/tt"
"github.com/status-im/status-go/waku"
)
func TestMessengerEmojiSuite(t *testing.T) {
suite.Run(t, new(MessengerEmojiSuite))
}
type MessengerEmojiSuite struct {
suite.Suite
m *Messenger // main instance of Messenger
privateKey *ecdsa.PrivateKey // private key for the main instance of Messenger
// If one wants to send messages between different instances of Messenger,
// a single Waku service should be shared.
shh types.Waku
tmpFiles []*os.File // files to clean up
logger *zap.Logger
}
func (s *MessengerEmojiSuite) SetupTest() {
s.logger = tt.MustCreateTestLogger()
config := waku.DefaultConfig
config.MinimumAcceptedPoW = 0
shh := waku.New(&config, s.logger)
s.shh = gethbridge.NewGethWakuWrapper(shh)
s.Require().NoError(shh.Start(nil))
s.m = s.newMessenger(s.shh)
s.privateKey = s.m.identity
}
func (s *MessengerEmojiSuite) newMessengerWithKey(shh types.Waku, privateKey *ecdsa.PrivateKey) *Messenger {
tmpFile, err := ioutil.TempFile("", "")
s.Require().NoError(err)
options := []Option{
WithCustomLogger(s.logger),
WithMessagesPersistenceEnabled(),
WithDatabaseConfig(tmpFile.Name(), "some-key"),
WithDatasync(),
}
installationID := uuid.New().String()
m, err := NewMessenger(
privateKey,
&testNode{shh: shh},
installationID,
options...,
)
s.Require().NoError(err)
err = m.Init()
s.Require().NoError(err)
s.tmpFiles = append(s.tmpFiles, tmpFile)
return m
}
func (s *MessengerEmojiSuite) newMessenger(shh types.Waku) *Messenger {
privateKey, err := crypto.GenerateKey()
s.Require().NoError(err)
return s.newMessengerWithKey(s.shh, privateKey)
}
func (s *MessengerEmojiSuite) TestSendEmoji() {
alice := s.m
key, err := crypto.GenerateKey()
s.Require().NoError(err)
bob := s.newMessengerWithKey(s.shh, key)
chatID := statusChatID
chat := CreatePublicChat(chatID, alice.transport)
err = alice.SaveChat(&chat)
s.Require().NoError(err)
err = alice.Join(chat)
s.Require().NoError(err)
err = bob.SaveChat(&chat)
s.Require().NoError(err)
err = bob.Join(chat)
s.Require().NoError(err)
// Send chat message from bob to alice
message := buildTestMessage(chat)
_, err = alice.SendChatMessage(context.Background(), message)
s.NoError(err)
// Wait for message to arrive to bob
response, err := WaitOnMessengerResponse(
bob,
func(r *MessengerResponse) bool { return len(r.Messages) > 0 },
"no messages",
)
s.Require().NoError(err)
s.Require().Len(response.Messages, 1)
messageID := response.Messages[0].ID
// Respond with an emoji, donald trump style
response, err = bob.SendEmojiReaction(context.Background(), chat.ID, messageID, protobuf.EmojiReaction_SAD)
s.Require().NoError(err)
s.Require().Len(response.EmojiReactions, 1)
emojiID := response.EmojiReactions[0].ID()
// Wait for the emoji to arrive to alice
response, err = WaitOnMessengerResponse(
alice,
func(r *MessengerResponse) bool { return len(r.EmojiReactions) > 0 },
"no emoji",
)
s.Require().NoError(err)
s.Require().Len(response.EmojiReactions, 1)
s.Require().Equal(response.EmojiReactions[0].ID(), emojiID)
s.Require().Equal(response.EmojiReactions[0].Type, protobuf.EmojiReaction_SAD)
// Retract the emoji
response, err = bob.SendEmojiReactionRetraction(context.Background(), emojiID)
s.Require().NoError(err)
s.Require().Len(response.EmojiReactions, 1)
s.Require().True(response.EmojiReactions[0].Retracted)
// Wait for the emoji to arrive to alice
response, err = WaitOnMessengerResponse(
alice,
func(r *MessengerResponse) bool { return len(r.EmojiReactions) > 0 },
"no emoji",
)
s.Require().NoError(err)
s.Require().Len(response.EmojiReactions, 1)
s.Require().Equal(response.EmojiReactions[0].ID(), emojiID)
s.Require().Equal(response.EmojiReactions[0].Type, protobuf.EmojiReaction_SAD)
s.Require().True(response.EmojiReactions[0].Retracted)
}
func (s *MessengerEmojiSuite) TestEmojiPrivateGroup() {
bob := s.m
alice := s.newMessenger(s.shh)
response, err := bob.CreateGroupChatWithMembers(context.Background(), "test", []string{})
s.NoError(err)
chat := response.Chats[0]
members := []string{types.EncodeHex(crypto.FromECDSAPub(&alice.identity.PublicKey))}
_, err = bob.AddMembersToGroupChat(context.Background(), chat.ID, members)
s.NoError(err)
// Retrieve their messages so that the chat is created
_, err = WaitOnMessengerResponse(
alice,
func(r *MessengerResponse) bool { return len(r.Chats) > 0 },
"chat invitation not received",
)
s.Require().NoError(err)
_, err = alice.ConfirmJoiningGroup(context.Background(), chat.ID)
s.NoError(err)
// Wait for the message to reach its destination
_, err = WaitOnMessengerResponse(
bob,
func(r *MessengerResponse) bool { return len(r.Chats) > 0 },
"no joining group event received",
)
s.Require().NoError(err)
inputMessage := buildTestMessage(*chat)
_, err = bob.SendChatMessage(context.Background(), inputMessage)
s.NoError(err)
// Wait for the message to reach its destination
response, err = WaitOnMessengerResponse(
alice,
func(r *MessengerResponse) bool { return len(r.Messages) > 0 },
"no message received",
)
s.Require().NoError(err)
messageID := response.Messages[0].ID
_, err = bob.SendEmojiReaction(context.Background(), chat.ID, messageID, protobuf.EmojiReaction_SAD)
s.Require().NoError(err)
// Wait for the message to reach its destination
_, err = WaitOnMessengerResponse(
alice,
func(r *MessengerResponse) bool { return len(r.EmojiReactions) > 0 },
"no emoji reaction received",
)
s.Require().NoError(err)
}

View File

@ -289,6 +289,5 @@ func (s *MessengerInstallationSuite) TestSyncInstallationNewMessages() {
func(r *MessengerResponse) bool { return len(r.Messages) > 0 },
"message not received",
)
s.Require().NoError(err)
}

View File

@ -295,11 +295,11 @@ func buildTestMessage(chat Chat) *Message {
message.ContentType = protobuf.ChatMessage_TEXT_PLAIN
switch chat.ChatType {
case ChatTypePublic:
message.MessageType = protobuf.ChatMessage_PUBLIC_GROUP
message.MessageType = protobuf.MessageType_PUBLIC_GROUP
case ChatTypeOneToOne:
message.MessageType = protobuf.ChatMessage_ONE_TO_ONE
message.MessageType = protobuf.MessageType_ONE_TO_ONE
case ChatTypePrivateGroupChat:
message.MessageType = protobuf.ChatMessage_PRIVATE_GROUP
message.MessageType = protobuf.MessageType_PRIVATE_GROUP
}
return message
@ -371,7 +371,7 @@ func (s *MessengerSuite) TestSendPublic() {
s.Require().True(outputMessage.Seen, "it marks the message as seen")
s.Require().Equal(outputMessage.OutgoingStatus, OutgoingStatusSending, "it marks the message as sending")
s.Require().NotEmpty(outputMessage.ID, "it sets the ID field")
s.Require().Equal(protobuf.ChatMessage_PUBLIC_GROUP, outputMessage.MessageType)
s.Require().Equal(protobuf.MessageType_PUBLIC_GROUP, outputMessage.MessageType)
savedMessages, _, err := s.m.MessageByChatID(chat.ID, "", 10)
s.Require().NoError(err)
@ -402,7 +402,7 @@ func (s *MessengerSuite) TestSendPrivateOneToOne() {
s.Require().True(outputMessage.Seen, "it marks the message as seen")
s.Require().Equal(outputMessage.OutgoingStatus, OutgoingStatusSending, "it marks the message as sending")
s.Require().NotEmpty(outputMessage.ID, "it sets the ID field")
s.Require().Equal(protobuf.ChatMessage_ONE_TO_ONE, outputMessage.MessageType)
s.Require().Equal(protobuf.MessageType_ONE_TO_ONE, outputMessage.MessageType)
}
func (s *MessengerSuite) TestSendPrivateGroup() {
@ -435,7 +435,7 @@ func (s *MessengerSuite) TestSendPrivateGroup() {
s.Require().True(outputMessage.Seen, "it marks the message as seen")
s.Require().Equal(outputMessage.OutgoingStatus, OutgoingStatusSending, "it marks the message as sending")
s.Require().NotEmpty(outputMessage.ID, "it sets the ID field")
s.Require().Equal(protobuf.ChatMessage_PRIVATE_GROUP, outputMessage.MessageType)
s.Require().Equal(protobuf.MessageType_PRIVATE_GROUP, outputMessage.MessageType)
}
func (s *MessengerSuite) TestSendPrivateEmptyGroup() {
@ -463,7 +463,7 @@ func (s *MessengerSuite) TestSendPrivateEmptyGroup() {
s.Require().True(outputMessage.Seen, "it marks the message as seen")
s.Require().Equal(outputMessage.OutgoingStatus, OutgoingStatusSending, "it marks the message as sending")
s.Require().NotEmpty(outputMessage.ID, "it sets the ID field")
s.Require().Equal(protobuf.ChatMessage_PRIVATE_GROUP, outputMessage.MessageType)
s.Require().Equal(protobuf.MessageType_PRIVATE_GROUP, outputMessage.MessageType)
}
// Make sure public messages sent by us are not
@ -2168,7 +2168,7 @@ func (s *MessageHandlerSuite) TestRun() {
Message: Message{
ChatMessage: protobuf.ChatMessage{
ChatId: "test-chat",
MessageType: protobuf.ChatMessage_PUBLIC_GROUP,
MessageType: protobuf.MessageType_PUBLIC_GROUP,
Text: "test-text"},
},
SigPubKey: &key1.PublicKey,
@ -2180,7 +2180,7 @@ func (s *MessageHandlerSuite) TestRun() {
Message: Message{
ChatMessage: protobuf.ChatMessage{
ChatId: "test-chat",
MessageType: protobuf.ChatMessage_ONE_TO_ONE,
MessageType: protobuf.MessageType_ONE_TO_ONE,
Text: "test-text"},
},
SigPubKey: &key1.PublicKey,
@ -2192,7 +2192,7 @@ func (s *MessageHandlerSuite) TestRun() {
Message: Message{
ChatMessage: protobuf.ChatMessage{
ChatId: "test-chat",
MessageType: protobuf.ChatMessage_ONE_TO_ONE,
MessageType: protobuf.MessageType_ONE_TO_ONE,
Text: "test-text"},
},
@ -2204,7 +2204,7 @@ func (s *MessageHandlerSuite) TestRun() {
Message: Message{
ChatMessage: protobuf.ChatMessage{
ChatId: "test-chat",
MessageType: protobuf.ChatMessage_ONE_TO_ONE,
MessageType: protobuf.MessageType_ONE_TO_ONE,
Text: "test-text"},
},
@ -2216,7 +2216,7 @@ func (s *MessageHandlerSuite) TestRun() {
Message: Message{
ChatMessage: protobuf.ChatMessage{
ChatId: "test-chat",
MessageType: protobuf.ChatMessage_ONE_TO_ONE,
MessageType: protobuf.MessageType_ONE_TO_ONE,
Text: "test-text"},
},
@ -2233,7 +2233,7 @@ func (s *MessageHandlerSuite) TestRun() {
Message: Message{
ChatMessage: protobuf.ChatMessage{
ChatId: "non-existing-chat",
MessageType: protobuf.ChatMessage_PRIVATE_GROUP,
MessageType: protobuf.MessageType_PRIVATE_GROUP,
Text: "test-text"},
},
Error: true,
@ -2254,7 +2254,7 @@ func (s *MessageHandlerSuite) TestRun() {
s.Empty(message.LocalChatID)
message.ID = strconv.Itoa(idx) // manually set the ID because messages does not go through messageProcessor
chat, err := s.messageHandler.matchMessage(&message, chatsMap, &testTimeSource{})
chat, err := s.messageHandler.matchChatEntity(&message, chatsMap, &testTimeSource{})
if tc.Error {
s.Require().Error(err)
} else {

View File

@ -16,6 +16,8 @@
// 1593087212_add_mute_chat_and_raw_message_fields.up.sql (215B)
// 1595862781_add_audio_data.down.sql (0)
// 1595862781_add_audio_data.up.sql (246B)
// 1595865249_create_emoji_reactions_table.down.sql (27B)
// 1595865249_create_emoji_reactions_table.up.sql (300B)
// doc.go (850B)
package migrations
@ -380,7 +382,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(0644), modTime: time.Unix(1595862768, 0)}
info := bindataFileInfo{name: "1595862781_add_audio_data.down.sql", size: 0, mode: os.FileMode(0644), modTime: time.Unix(1595864522, 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
}
@ -400,11 +402,51 @@ func _1595862781_add_audio_dataUpSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1595862781_add_audio_data.up.sql", size: 246, mode: os.FileMode(0644), modTime: time.Unix(1595862893, 0)}
info := bindataFileInfo{name: "1595862781_add_audio_data.up.sql", size: 246, mode: os.FileMode(0644), modTime: time.Unix(1595864522, 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
}
var __1595865249_create_emoji_reactions_tableDownSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x72\x09\xf2\x0f\x50\x08\x71\x74\xf2\x71\x55\x48\xcd\xcd\xcf\xca\x8c\x2f\x4a\x4d\x4c\x2e\xc9\xcc\xcf\x2b\xb6\x06\x04\x00\x00\xff\xff\x54\xc5\xdd\x49\x1b\x00\x00\x00")
func _1595865249_create_emoji_reactions_tableDownSqlBytes() ([]byte, error) {
return bindataRead(
__1595865249_create_emoji_reactions_tableDownSql,
"1595865249_create_emoji_reactions_table.down.sql",
)
}
func _1595865249_create_emoji_reactions_tableDownSql() (*asset, error) {
bytes, err := _1595865249_create_emoji_reactions_tableDownSqlBytes()
if err != nil {
return nil, err
}
info := bindataFileInfo{name: "1595865249_create_emoji_reactions_table.down.sql", size: 27, mode: os.FileMode(0644), modTime: time.Unix(1595865239, 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
}
var __1595865249_create_emoji_reactions_tableUpSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x7c\xce\xbd\x4e\x03\x31\x10\x04\xe0\xfe\xa4\x7b\x87\x29\x41\xa2\xa0\xa7\x32\x66\x4f\x58\x18\x5f\xe4\x6c\x50\x52\x9d\x2c\x67\x05\x07\x0e\x96\x6c\x87\xe7\x47\xe4\x1a\x7e\x44\xea\x6f\x76\x67\xb4\x27\xc5\x04\x56\xb7\x96\x60\x06\xb8\x91\x41\x5b\xb3\xe6\x35\xe4\x90\x5f\xe7\xa9\x48\x88\x6d\xce\xef\x15\x17\x7d\x07\xcc\x7b\x3c\x29\xaf\xef\x95\xc7\xca\x9b\x47\xe5\x77\x78\xa0\x1d\x46\x07\x3d\xba\xc1\x1a\xcd\xf0\xb4\xb2\x4a\xd3\xd5\x57\x3c\xa6\x1c\xdf\xa6\x8f\x90\x8e\x02\xe3\xf8\xf4\xde\x6d\xac\x3d\x61\xcd\xc7\x12\x05\x4c\xdb\x5f\xb0\x34\xcf\xfb\xbf\x27\x07\xa9\x35\x3c\xcb\xf4\x6d\xc6\x0f\x8f\x2f\xa1\xfd\x8b\x29\xc7\x90\xa6\xb3\x91\x22\xad\x84\xd8\x64\xa9\xbe\xa3\x41\x6d\x2c\xe3\xba\xef\x2e\x6f\xfa\xee\x33\x00\x00\xff\xff\xe4\x28\x05\xe0\x2c\x01\x00\x00")
func _1595865249_create_emoji_reactions_tableUpSqlBytes() ([]byte, error) {
return bindataRead(
__1595865249_create_emoji_reactions_tableUpSql,
"1595865249_create_emoji_reactions_table.up.sql",
)
}
func _1595865249_create_emoji_reactions_tableUpSql() (*asset, error) {
bytes, err := _1595865249_create_emoji_reactions_tableUpSqlBytes()
if err != nil {
return nil, err
}
info := bindataFileInfo{name: "1595865249_create_emoji_reactions_table.up.sql", size: 300, mode: os.FileMode(0644), modTime: time.Unix(1595921491, 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
}
var _docGo = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x84\x52\x3f\x8f\xdb\x3e\x0c\xdd\xf3\x29\x1e\x6e\xb9\xe5\x22\x07\xf8\xfd\xa6\xdb\x3a\x74\xe8\xd2\x2e\xd9\x0b\x46\xa6\x6d\x22\x32\xe5\x8a\xf4\x39\xf9\xf6\x85\x74\x17\x9c\x51\x14\xe8\x4a\x89\x8f\xef\x5f\xd7\xe1\x3c\x89\x61\x90\xc4\x10\x83\x72\x64\x33\x2a\x77\x5c\x38\xd2\x6a\x8c\xa7\x51\x7c\x5a\x2f\x21\xe6\xb9\x33\x27\x5f\xed\x28\x73\x37\xcb\x58\xc8\xb9\x7b\xfb\xff\xe9\xd0\x75\x88\xa4\xcf\x8e\x89\xb4\x4f\xdc\xb0\x0c\xe6\x54\x5c\x74\xc4\x26\x3e\x81\xb0\x14\x1e\xe4\x16\xf0\xc5\x91\x98\xcc\xe1\x13\xf9\xb3\xc1\x27\x46\x24\xe3\x0a\x33\xe4\x82\x31\x1f\x2f\xa2\x3d\x39\x85\x3a\xfa\x36\xec\x26\x95\x61\xa4\x94\xb8\xc7\x50\xf2\xdc\x76\x8d\x66\x46\x2f\x85\xa3\xe7\x72\x7f\x01\x99\xb1\x43\x69\x66\xab\xfb\x13\xbd\x31\x34\x7f\x9c\x07\x69\xff\x6f\x45\xd8\x72\xb9\x1a\xc8\xc0\xb7\x85\xa3\x73\x1f\x0e\x15\xeb\xfb\x8f\xf3\xd7\x57\x9c\x27\xae\xf0\x55\x5a\x1e\x1a\x85\x66\x9e\x32\xf7\x06\xcf\x18\x72\x4a\x79\x6b\x0f\xab\xca\x0d\x2e\x33\x9b\xd3\xbc\x20\x66\x7d\x63\x75\xc9\x5a\xd1\x56\x4d\x72\xe5\xf6\xcf\xb7\x0c\x51\x71\xa1\xf4\xee\x5e\x93\x7e\x7e\x37\xe8\x11\x44\x5c\x4b\x61\xf5\x74\x6f\x2b\xac\xb1\xdc\x97\x8a\x85\x77\xe6\x92\xd5\x9a\xbc\xa5\x64\xcf\x31\xa7\xdd\xbc\xa2\xd9\x44\x85\x3f\x1d\x73\xba\x24\x7e\xc1\x36\x49\x9c\x30\x33\xa9\xb5\x40\xda\x87\x44\xce\xe6\x9f\xfb\x10\x85\x73\x99\xad\x0a\xae\xfc\xaa\xbb\x15\xb3\x16\xe7\x91\xc3\x8e\x50\x33\x7f\xa1\xf8\x51\x85\xc7\x95\xd5\xd8\x40\x7f\x98\xf2\x08\x79\x63\x50\xdf\xe3\x74\x3a\x9d\xfe\xfb\x19\x42\x68\x5d\xe0\x1b\xcd\x4b\xa5\xe9\xb5\xa3\x9b\xa4\x84\x0b\x43\x46\xcd\x85\xfb\xca\x8a\x6f\x62\xad\x64\x31\x09\xab\xd7\xcc\x2a\x5e\x4e\x3d\x97\xaa\x47\xf7\x7a\xfe\x66\x59\x38\x1c\x16\x8a\x57\x1a\x19\xf6\x2b\x89\x73\x0d\x7a\xcc\xaf\x23\x2b\xd7\x3a\xec\xcb\x77\x5c\xae\xe3\xde\xec\x63\x46\x08\xdd\xe7\x20\x8c\x19\xe1\xf0\x3b\x00\x00\xff\xff\x12\xcd\x7f\xc4\x52\x03\x00\x00")
func docGoBytes() ([]byte, error) {
@ -548,6 +590,10 @@ var _bindata = map[string]func() (*asset, error){
"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,
"doc.go": docGo,
}
@ -608,7 +654,9 @@ var _bintree = &bintree{nil, 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{}},
"doc.go": &bintree{docGo, 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{}},
"doc.go": &bintree{docGo, map[string]*bintree{}},
}}
// RestoreAsset restores an asset under the given directory.

View File

@ -0,0 +1 @@
DROP TABLE emoji_reactions;

View File

@ -0,0 +1,10 @@
CREATE TABLE IF NOT EXISTS emoji_reactions (
id VARCHAR PRIMARY KEY ON CONFLICT REPLACE,
clock_value INT NOT NULL,
source TEXT NOT NULL,
emoji_id INT NOT NULL,
message_id VARCHAR NOT NULL,
chat_id VARCHAR NOT NULL,
local_chat_id VARCHAR NOT NULL,
retracted INT DEFAULT 0
);

View File

@ -375,6 +375,107 @@ func TestUpdateMessageOutgoingStatus(t *testing.T) {
require.Equal(t, "new-status", m.OutgoingStatus)
}
func TestPersistenceEmojiReactions(t *testing.T) {
db, err := openTestDB()
require.NoError(t, err)
p := sqlitePersistence{db: db}
// reverse order as we use DESC
id1 := "1"
id2 := "2"
id3 := "3"
from1 := "from-1"
from2 := "from-2"
from3 := "from-3"
chatID := "chat-id"
err = insertMinimalMessage(p, id1)
require.NoError(t, err)
err = insertMinimalMessage(p, id2)
require.NoError(t, err)
err = insertMinimalMessage(p, id3)
require.NoError(t, err)
// Insert normal emoji reaction
require.NoError(t, p.SaveEmojiReaction(&EmojiReaction{
EmojiReaction: protobuf.EmojiReaction{
Clock: 1,
MessageId: id3,
ChatId: chatID,
Type: protobuf.EmojiReaction_SAD,
},
LocalChatID: chatID,
From: from1,
}))
// Insert retracted emoji reaction
require.NoError(t, p.SaveEmojiReaction(&EmojiReaction{
EmojiReaction: protobuf.EmojiReaction{
Clock: 1,
MessageId: id3,
ChatId: chatID,
Type: protobuf.EmojiReaction_SAD,
Retracted: true,
},
LocalChatID: chatID,
From: from2,
}))
// Insert retracted emoji reaction out of pagination
require.NoError(t, p.SaveEmojiReaction(&EmojiReaction{
EmojiReaction: protobuf.EmojiReaction{
Clock: 1,
MessageId: id1,
ChatId: chatID,
Type: protobuf.EmojiReaction_SAD,
},
LocalChatID: chatID,
From: from2,
}))
// Insert retracted emoji reaction out of pagination
require.NoError(t, p.SaveEmojiReaction(&EmojiReaction{
EmojiReaction: protobuf.EmojiReaction{
Clock: 1,
MessageId: id1,
ChatId: chatID,
Type: protobuf.EmojiReaction_SAD,
},
LocalChatID: chatID,
From: from3,
}))
// Wrong local chat id
require.NoError(t, p.SaveEmojiReaction(&EmojiReaction{
EmojiReaction: protobuf.EmojiReaction{
Clock: 1,
MessageId: id1,
ChatId: chatID,
Type: protobuf.EmojiReaction_LOVE,
},
LocalChatID: "wrong-chat-id",
From: from3,
}))
reactions, err := p.EmojiReactionsByChatID(chatID, "", 1)
require.NoError(t, err)
require.Len(t, reactions, 1)
require.Equal(t, id3, reactions[0].MessageId)
// Try with a cursor
_, cursor, err := p.MessageByChatID(chatID, "", 1)
require.NoError(t, err)
reactions, err = p.EmojiReactionsByChatID(chatID, cursor, 2)
require.NoError(t, err)
require.Len(t, reactions, 2)
require.Equal(t, id1, reactions[0].MessageId)
require.Equal(t, id1, reactions[1].MessageId)
}
func openTestDB() (*sql.DB, error) {
dbPath, err := ioutil.TempFile("", "")
if err != nil {

View File

@ -45,6 +45,8 @@ const (
ApplicationMetadataMessage_PUSH_NOTIFICATION_QUERY_RESPONSE ApplicationMetadataMessage_Type = 19
ApplicationMetadataMessage_PUSH_NOTIFICATION_REQUEST ApplicationMetadataMessage_Type = 20
ApplicationMetadataMessage_PUSH_NOTIFICATION_RESPONSE ApplicationMetadataMessage_Type = 21
ApplicationMetadataMessage_EMOJI_REACTION ApplicationMetadataMessage_Type = 22
ApplicationMetadataMessage_EMOJI_REACTION_RETRACTION ApplicationMetadataMessage_Type = 23
)
var ApplicationMetadataMessage_Type_name = map[int32]string{
@ -70,6 +72,8 @@ var ApplicationMetadataMessage_Type_name = map[int32]string{
19: "PUSH_NOTIFICATION_QUERY_RESPONSE",
20: "PUSH_NOTIFICATION_REQUEST",
21: "PUSH_NOTIFICATION_RESPONSE",
22: "EMOJI_REACTION",
23: "EMOJI_REACTION_RETRACTION",
}
var ApplicationMetadataMessage_Type_value = map[string]int32{
@ -95,6 +99,8 @@ var ApplicationMetadataMessage_Type_value = map[string]int32{
"PUSH_NOTIFICATION_QUERY_RESPONSE": 19,
"PUSH_NOTIFICATION_REQUEST": 20,
"PUSH_NOTIFICATION_RESPONSE": 21,
"EMOJI_REACTION": 22,
"EMOJI_REACTION_RETRACTION": 23,
}
func (x ApplicationMetadataMessage_Type) String() string {
@ -171,34 +177,36 @@ func init() {
func init() { proto.RegisterFile("application_metadata_message.proto", fileDescriptor_ad09a6406fcf24c7) }
var fileDescriptor_ad09a6406fcf24c7 = []byte{
// 463 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x92, 0x51, 0x4f, 0x13, 0x41,
0x10, 0xc7, 0x2d, 0x94, 0x16, 0x86, 0x5a, 0x97, 0x01, 0x42, 0x05, 0x81, 0x5a, 0x8d, 0xa2, 0x26,
0x7d, 0xd0, 0x67, 0x1f, 0x96, 0xbd, 0x81, 0x6e, 0xec, 0xed, 0x1d, 0xbb, 0x7b, 0x1a, 0x9e, 0x36,
0x87, 0x9c, 0xa4, 0x09, 0xd0, 0x0b, 0x3d, 0x1e, 0xfa, 0x8d, 0xfc, 0x14, 0x7e, 0x36, 0x73, 0xd7,
0xd6, 0x82, 0x2d, 0xf0, 0x74, 0xd9, 0xff, 0xff, 0x37, 0x33, 0x99, 0xff, 0x1c, 0xb4, 0xe2, 0x34,
0xbd, 0xec, 0xfd, 0x8c, 0xb3, 0x5e, 0xff, 0xda, 0x5d, 0x25, 0x59, 0x7c, 0x1e, 0x67, 0xb1, 0xbb,
0x4a, 0x06, 0x83, 0xf8, 0x22, 0x69, 0xa7, 0x37, 0xfd, 0xac, 0x8f, 0xcb, 0xc5, 0xe7, 0xec, 0xf6,
0x57, 0xeb, 0x4f, 0x05, 0xb6, 0xf9, 0xb4, 0xc0, 0x1f, 0xf3, 0xfe, 0x08, 0xc7, 0x57, 0xb0, 0x32,
0xe8, 0x5d, 0x5c, 0xc7, 0xd9, 0xed, 0x4d, 0xd2, 0x28, 0x35, 0x4b, 0x07, 0x35, 0x3d, 0x15, 0xb0,
0x01, 0xd5, 0x34, 0x1e, 0x5e, 0xf6, 0xe3, 0xf3, 0xc6, 0x42, 0xe1, 0x4d, 0x9e, 0xf8, 0x15, 0xca,
0xd9, 0x30, 0x4d, 0x1a, 0x8b, 0xcd, 0xd2, 0x41, 0xfd, 0xf3, 0x87, 0xf6, 0x64, 0x5e, 0xfb, 0xe1,
0x59, 0x6d, 0x3b, 0x4c, 0x13, 0x5d, 0x94, 0xb5, 0x7e, 0x2f, 0x41, 0x39, 0x7f, 0xe2, 0x2a, 0x54,
0x23, 0xf5, 0x4d, 0x05, 0x3f, 0x14, 0x7b, 0x86, 0x0c, 0x6a, 0xa2, 0xc3, 0xad, 0xf3, 0xc9, 0x18,
0x7e, 0x4c, 0xac, 0x84, 0x08, 0x75, 0x11, 0x28, 0xcb, 0x85, 0x75, 0x51, 0xe8, 0x71, 0x4b, 0x6c,
0x01, 0x77, 0xe1, 0xa5, 0x4f, 0xfe, 0x21, 0x69, 0xd3, 0x91, 0xe1, 0x58, 0xfe, 0x57, 0xb2, 0x88,
0x9b, 0xb0, 0x16, 0x72, 0xa9, 0x9d, 0x54, 0xc6, 0xf2, 0x6e, 0x97, 0x5b, 0x19, 0x28, 0x56, 0xce,
0x65, 0x73, 0xaa, 0xc4, 0x7d, 0x79, 0x09, 0xdf, 0xc0, 0xbe, 0xa6, 0x93, 0x88, 0x8c, 0x75, 0xdc,
0xf3, 0x34, 0x19, 0xe3, 0x8e, 0x02, 0xed, 0xac, 0xe6, 0xca, 0x70, 0x51, 0x40, 0x15, 0xfc, 0x08,
0xef, 0xb8, 0x10, 0x14, 0x5a, 0xf7, 0x14, 0x5b, 0xc5, 0x4f, 0xf0, 0xde, 0x23, 0xd1, 0x95, 0x8a,
0x9e, 0x84, 0x97, 0x71, 0x0b, 0xd6, 0x27, 0xd0, 0x5d, 0x63, 0x05, 0x37, 0x80, 0x19, 0x52, 0xde,
0x3d, 0x15, 0x70, 0x1f, 0x76, 0xfe, 0xef, 0x7d, 0x17, 0x58, 0xcd, 0xa3, 0x99, 0x59, 0xd2, 0x8d,
0x03, 0x64, 0xb5, 0xf9, 0x36, 0x17, 0x22, 0x88, 0x94, 0x65, 0xcf, 0xf1, 0x35, 0xec, 0xce, 0xda,
0x61, 0x74, 0xd8, 0x95, 0xc2, 0xe5, 0x77, 0x61, 0x75, 0xdc, 0x83, 0xed, 0xc9, 0x3d, 0x44, 0xe0,
0x91, 0xe3, 0xde, 0x77, 0xd2, 0x56, 0x1a, 0xf2, 0x49, 0x59, 0xf6, 0x02, 0x5b, 0xb0, 0x17, 0x46,
0xa6, 0xe3, 0x54, 0x60, 0xe5, 0x91, 0x14, 0xa3, 0x16, 0x9a, 0x8e, 0xa5, 0xb1, 0x7a, 0x14, 0x39,
0xcb, 0x13, 0x7a, 0x9c, 0x71, 0x9a, 0x4c, 0x18, 0x28, 0x43, 0x6c, 0x0d, 0x77, 0x60, 0x6b, 0x16,
0x3e, 0x89, 0x48, 0x9f, 0x32, 0xc4, 0xb7, 0xd0, 0x7c, 0xc0, 0x9c, 0xb6, 0x58, 0xcf, 0xb7, 0x9e,
0x37, 0xaf, 0xc8, 0x8f, 0x6d, 0xe4, 0x2b, 0xcd, 0xb3, 0xc7, 0xe5, 0x9b, 0x67, 0x95, 0xe2, 0xd7,
0xfe, 0xf2, 0x37, 0x00, 0x00, 0xff, 0xff, 0xe7, 0xcd, 0xf5, 0xf1, 0x77, 0x03, 0x00, 0x00,
// 486 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x93, 0xd1, 0x52, 0xd3, 0x4e,
0x14, 0xc6, 0xff, 0x85, 0xd2, 0xc2, 0xa1, 0xff, 0xba, 0x1c, 0xc0, 0x56, 0x10, 0xa8, 0xd5, 0x51,
0xd4, 0x99, 0x5e, 0xe8, 0xb5, 0x17, 0xcb, 0xe6, 0x40, 0xa3, 0xcd, 0x26, 0xec, 0x6e, 0x74, 0xb8,
0xda, 0x09, 0x12, 0x99, 0xce, 0x00, 0xcd, 0xd0, 0x70, 0xd1, 0x67, 0xf5, 0x29, 0x7c, 0x03, 0x27,
0x69, 0x6a, 0xa9, 0x2d, 0x72, 0x95, 0xd9, 0xef, 0xfb, 0x9d, 0x73, 0xe6, 0x7c, 0x9b, 0x85, 0x76,
0x94, 0x24, 0x57, 0xfd, 0xef, 0x51, 0xda, 0x1f, 0xdc, 0xd8, 0xeb, 0x38, 0x8d, 0x2e, 0xa2, 0x34,
0xb2, 0xd7, 0xf1, 0x70, 0x18, 0x5d, 0xc6, 0x9d, 0xe4, 0x76, 0x90, 0x0e, 0x70, 0x35, 0xff, 0x9c,
0xdf, 0xfd, 0x68, 0xff, 0xaa, 0xc0, 0x0e, 0x9f, 0x16, 0x78, 0x05, 0xef, 0x8d, 0x71, 0x7c, 0x0e,
0x6b, 0xc3, 0xfe, 0xe5, 0x4d, 0x94, 0xde, 0xdd, 0xc6, 0xcd, 0x52, 0xab, 0x74, 0x58, 0x53, 0x53,
0x01, 0x9b, 0x50, 0x4d, 0xa2, 0xd1, 0xd5, 0x20, 0xba, 0x68, 0x2e, 0xe5, 0xde, 0xe4, 0x88, 0x9f,
0xa0, 0x9c, 0x8e, 0x92, 0xb8, 0xb9, 0xdc, 0x2a, 0x1d, 0xd6, 0x3f, 0xbc, 0xed, 0x4c, 0xe6, 0x75,
0x1e, 0x9e, 0xd5, 0x31, 0xa3, 0x24, 0x56, 0x79, 0x59, 0xfb, 0xe7, 0x0a, 0x94, 0xb3, 0x23, 0xae,
0x43, 0x35, 0x94, 0x5f, 0xa4, 0xff, 0x4d, 0xb2, 0xff, 0x90, 0x41, 0x4d, 0x74, 0xb9, 0xb1, 0x1e,
0x69, 0xcd, 0x4f, 0x88, 0x95, 0x10, 0xa1, 0x2e, 0x7c, 0x69, 0xb8, 0x30, 0x36, 0x0c, 0x1c, 0x6e,
0x88, 0x2d, 0xe1, 0x1e, 0x3c, 0xf3, 0xc8, 0x3b, 0x22, 0xa5, 0xbb, 0x6e, 0x50, 0xc8, 0x7f, 0x4a,
0x96, 0x71, 0x1b, 0x36, 0x02, 0xee, 0x2a, 0xeb, 0x4a, 0x6d, 0x78, 0xaf, 0xc7, 0x8d, 0xeb, 0x4b,
0x56, 0xce, 0x64, 0x7d, 0x26, 0xc5, 0xac, 0xbc, 0x82, 0x2f, 0xe1, 0x40, 0xd1, 0x69, 0x48, 0xda,
0x58, 0xee, 0x38, 0x8a, 0xb4, 0xb6, 0xc7, 0xbe, 0xb2, 0x46, 0x71, 0xa9, 0xb9, 0xc8, 0xa1, 0x0a,
0xbe, 0x83, 0xd7, 0x5c, 0x08, 0x0a, 0x8c, 0x7d, 0x8c, 0xad, 0xe2, 0x7b, 0x78, 0xe3, 0x90, 0xe8,
0xb9, 0x92, 0x1e, 0x85, 0x57, 0xb1, 0x01, 0x9b, 0x13, 0xe8, 0xbe, 0xb1, 0x86, 0x5b, 0xc0, 0x34,
0x49, 0x67, 0x46, 0x05, 0x3c, 0x80, 0xdd, 0xbf, 0x7b, 0xdf, 0x07, 0xd6, 0xb3, 0x68, 0xe6, 0x96,
0xb4, 0x45, 0x80, 0xac, 0xb6, 0xd8, 0xe6, 0x42, 0xf8, 0xa1, 0x34, 0xec, 0x7f, 0x7c, 0x01, 0x7b,
0xf3, 0x76, 0x10, 0x1e, 0xf5, 0x5c, 0x61, 0xb3, 0x7b, 0x61, 0x75, 0xdc, 0x87, 0x9d, 0xc9, 0x7d,
0x08, 0xdf, 0x21, 0xcb, 0x9d, 0xaf, 0xa4, 0x8c, 0xab, 0xc9, 0x23, 0x69, 0xd8, 0x13, 0x6c, 0xc3,
0x7e, 0x10, 0xea, 0xae, 0x95, 0xbe, 0x71, 0x8f, 0x5d, 0x31, 0x6e, 0xa1, 0xe8, 0xc4, 0xd5, 0x46,
0x8d, 0x23, 0x67, 0x59, 0x42, 0xff, 0x66, 0xac, 0x22, 0x1d, 0xf8, 0x52, 0x13, 0xdb, 0xc0, 0x5d,
0x68, 0xcc, 0xc3, 0xa7, 0x21, 0xa9, 0x33, 0x86, 0xf8, 0x0a, 0x5a, 0x0f, 0x98, 0xd3, 0x16, 0x9b,
0xd9, 0xd6, 0x8b, 0xe6, 0xe5, 0xf9, 0xb1, 0xad, 0x6c, 0xa5, 0x45, 0x76, 0x51, 0xbe, 0x9d, 0xfd,
0x82, 0xe4, 0xf9, 0x9f, 0x5d, 0xab, 0xa8, 0xc8, 0xf9, 0x69, 0xd6, 0x72, 0x56, 0xb3, 0x8a, 0x8c,
0x2a, 0xec, 0xc6, 0x79, 0x25, 0x7f, 0x0d, 0x1f, 0x7f, 0x07, 0x00, 0x00, 0xff, 0xff, 0x79, 0x47,
0x6f, 0x0d, 0xaa, 0x03, 0x00, 0x00,
}

View File

@ -34,5 +34,7 @@ message ApplicationMetadataMessage {
PUSH_NOTIFICATION_QUERY_RESPONSE = 19;
PUSH_NOTIFICATION_REQUEST = 20;
PUSH_NOTIFICATION_RESPONSE = 21;
EMOJI_REACTION = 22;
EMOJI_REACTION_RETRACTION = 23;
}
}

View File

@ -82,41 +82,6 @@ func (AudioMessage_AudioType) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_263952f55fd35689, []int{2, 0}
}
type ChatMessage_MessageType int32
const (
ChatMessage_UNKNOWN_MESSAGE_TYPE ChatMessage_MessageType = 0
ChatMessage_ONE_TO_ONE ChatMessage_MessageType = 1
ChatMessage_PUBLIC_GROUP ChatMessage_MessageType = 2
ChatMessage_PRIVATE_GROUP ChatMessage_MessageType = 3
// Only local
ChatMessage_SYSTEM_MESSAGE_PRIVATE_GROUP ChatMessage_MessageType = 4
)
var ChatMessage_MessageType_name = map[int32]string{
0: "UNKNOWN_MESSAGE_TYPE",
1: "ONE_TO_ONE",
2: "PUBLIC_GROUP",
3: "PRIVATE_GROUP",
4: "SYSTEM_MESSAGE_PRIVATE_GROUP",
}
var ChatMessage_MessageType_value = map[string]int32{
"UNKNOWN_MESSAGE_TYPE": 0,
"ONE_TO_ONE": 1,
"PUBLIC_GROUP": 2,
"PRIVATE_GROUP": 3,
"SYSTEM_MESSAGE_PRIVATE_GROUP": 4,
}
func (x ChatMessage_MessageType) String() string {
return proto.EnumName(ChatMessage_MessageType_name, int32(x))
}
func (ChatMessage_MessageType) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_263952f55fd35689, []int{3, 0}
}
type ChatMessage_ContentType int32
const (
@ -161,7 +126,7 @@ func (x ChatMessage_ContentType) String() string {
}
func (ChatMessage_ContentType) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_263952f55fd35689, []int{3, 1}
return fileDescriptor_263952f55fd35689, []int{3, 0}
}
type StickerMessage struct {
@ -331,7 +296,7 @@ type ChatMessage struct {
// Probably should be the concatenation of sender-pk & receiver-pk in alphabetical order
ChatId string `protobuf:"bytes,6,opt,name=chat_id,json=chatId,proto3" json:"chat_id,omitempty"`
// The type of message (public/one-to-one/private-group-chat)
MessageType ChatMessage_MessageType `protobuf:"varint,7,opt,name=message_type,json=messageType,proto3,enum=protobuf.ChatMessage_MessageType" json:"message_type,omitempty"`
MessageType MessageType `protobuf:"varint,7,opt,name=message_type,json=messageType,proto3,enum=protobuf.MessageType" json:"message_type,omitempty"`
// The type of the content of the message
ContentType ChatMessage_ContentType `protobuf:"varint,8,opt,name=content_type,json=contentType,proto3,enum=protobuf.ChatMessage_ContentType" json:"content_type,omitempty"`
// Types that are valid to be assigned to Payload:
@ -411,11 +376,11 @@ func (m *ChatMessage) GetChatId() string {
return ""
}
func (m *ChatMessage) GetMessageType() ChatMessage_MessageType {
func (m *ChatMessage) GetMessageType() MessageType {
if m != nil {
return m.MessageType
}
return ChatMessage_UNKNOWN_MESSAGE_TYPE
return MessageType_UNKNOWN_MESSAGE_TYPE
}
func (m *ChatMessage) GetContentType() ChatMessage_ContentType {
@ -487,7 +452,6 @@ func (*ChatMessage) XXX_OneofWrappers() []interface{} {
func init() {
proto.RegisterEnum("protobuf.ImageMessage_ImageType", ImageMessage_ImageType_name, ImageMessage_ImageType_value)
proto.RegisterEnum("protobuf.AudioMessage_AudioType", AudioMessage_AudioType_name, AudioMessage_AudioType_value)
proto.RegisterEnum("protobuf.ChatMessage_MessageType", ChatMessage_MessageType_name, ChatMessage_MessageType_value)
proto.RegisterEnum("protobuf.ChatMessage_ContentType", ChatMessage_ContentType_name, ChatMessage_ContentType_value)
proto.RegisterType((*StickerMessage)(nil), "protobuf.StickerMessage")
proto.RegisterType((*ImageMessage)(nil), "protobuf.ImageMessage")
@ -498,46 +462,44 @@ func init() {
func init() { proto.RegisterFile("chat_message.proto", fileDescriptor_263952f55fd35689) }
var fileDescriptor_263952f55fd35689 = []byte{
// 652 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x53, 0x4d, 0x6f, 0xd3, 0x40,
0x10, 0xad, 0x13, 0x27, 0x8e, 0xc7, 0xa1, 0x5a, 0x96, 0xaa, 0x35, 0x52, 0x25, 0x82, 0xc5, 0x21,
0xa7, 0x1c, 0x4a, 0x91, 0xb8, 0xba, 0xae, 0x49, 0xdd, 0xd6, 0x1f, 0x5a, 0x6f, 0x28, 0x3d, 0x59,
0xae, 0xb3, 0x34, 0x51, 0xeb, 0x0f, 0xc5, 0xae, 0x44, 0x2f, 0xfc, 0x04, 0xfe, 0x07, 0x77, 0xc4,
0xef, 0x43, 0xbb, 0xae, 0x13, 0xa7, 0x42, 0x5c, 0x38, 0x79, 0x66, 0xf6, 0xcd, 0xf3, 0x9b, 0xd9,
0xb7, 0x80, 0x93, 0x45, 0x5c, 0x45, 0x29, 0x2b, 0xcb, 0xf8, 0x96, 0x4d, 0x8a, 0x55, 0x5e, 0xe5,
0x78, 0x20, 0x3e, 0x37, 0x0f, 0x5f, 0x8d, 0x8f, 0xb0, 0x1b, 0x56, 0xcb, 0xe4, 0x8e, 0xad, 0xdc,
0x1a, 0x81, 0x31, 0xc8, 0x8b, 0xb8, 0x5c, 0xe8, 0xd2, 0x48, 0x1a, 0xab, 0x44, 0xc4, 0xbc, 0x56,
0xc4, 0xc9, 0x9d, 0xde, 0x19, 0x49, 0xe3, 0x1e, 0x11, 0xb1, 0xf1, 0x53, 0x82, 0xa1, 0x93, 0xc6,
0xb7, 0xac, 0x69, 0xd4, 0x41, 0x29, 0xe2, 0xc7, 0xfb, 0x3c, 0x9e, 0x8b, 0xde, 0x21, 0x69, 0x52,
0x7c, 0x0c, 0x72, 0xf5, 0x58, 0x30, 0xd1, 0xbe, 0x7b, 0x34, 0x9a, 0x34, 0x7f, 0x9f, 0xb4, 0xfb,
0xeb, 0x84, 0x3e, 0x16, 0x8c, 0x08, 0xb4, 0xe1, 0x80, 0xba, 0x2e, 0xe1, 0x7d, 0xc0, 0x33, 0xef,
0xc2, 0xf3, 0xaf, 0xbc, 0xc8, 0x71, 0xcd, 0xa9, 0x1d, 0xd1, 0xeb, 0xc0, 0x46, 0x3b, 0x58, 0x81,
0x6e, 0xe0, 0x4d, 0x91, 0x84, 0x07, 0x20, 0x9f, 0x07, 0xf6, 0x14, 0x75, 0x78, 0x74, 0x65, 0x9f,
0x04, 0xa8, 0xcb, 0x0f, 0xa7, 0xce, 0x27, 0x24, 0x1b, 0xbf, 0x25, 0x18, 0x9a, 0x0f, 0xf3, 0x65,
0xfe, 0x1f, 0x5a, 0xdb, 0xfd, 0x75, 0xb2, 0xd1, 0x8a, 0xdf, 0x80, 0x36, 0x7f, 0x58, 0xc5, 0xd5,
0x32, 0xcf, 0xa2, 0xb4, 0xd4, 0xbb, 0x23, 0x69, 0x2c, 0x13, 0x68, 0x4a, 0x6e, 0x69, 0x7c, 0x00,
0x75, 0xdd, 0xd3, 0x1e, 0xc6, 0x9c, 0x9d, 0x3a, 0x7e, 0x6b, 0x18, 0xd3, 0xb4, 0x90, 0x24, 0x02,
0x97, 0xa0, 0x8e, 0xf1, 0xa3, 0x0f, 0x9a, 0xb5, 0x88, 0xab, 0x46, 0xf7, 0x1e, 0xf4, 0x92, 0xfb,
0x3c, 0xb9, 0x13, 0xaa, 0x65, 0x52, 0x27, 0xf8, 0x10, 0xd4, 0x6a, 0x99, 0xb2, 0xb2, 0x8a, 0xd3,
0x42, 0x08, 0x97, 0xc9, 0xa6, 0xc0, 0x2f, 0xaf, 0x62, 0xdf, 0x2a, 0x21, 0x4a, 0x25, 0x22, 0xe6,
0x7a, 0x57, 0xac, 0x2c, 0xf2, 0xac, 0x64, 0x51, 0x95, 0xeb, 0xb2, 0x38, 0x82, 0xa6, 0x44, 0x73,
0xfc, 0x1a, 0x06, 0x2c, 0x2b, 0xa3, 0x2c, 0x4e, 0x99, 0xde, 0x13, 0xa7, 0x0a, 0xcb, 0x4a, 0x2f,
0x4e, 0x19, 0x3e, 0x00, 0x45, 0x58, 0x6a, 0x39, 0xd7, 0xfb, 0xe2, 0xa4, 0xcf, 0x53, 0x67, 0x8e,
0x4f, 0x61, 0xf8, 0x64, 0xb3, 0x48, 0xac, 0x50, 0x11, 0x2b, 0x7c, 0xbb, 0x59, 0x61, 0x6b, 0x92,
0xc9, 0xd3, 0x57, 0xec, 0x50, 0x4b, 0x37, 0x09, 0x67, 0x49, 0xf2, 0xac, 0x62, 0x59, 0x55, 0xb3,
0x0c, 0xfe, 0xc5, 0x62, 0xd5, 0xc8, 0x9a, 0x25, 0xd9, 0x24, 0xf8, 0x18, 0x94, 0xb2, 0xf6, 0xb5,
0xae, 0x8e, 0xa4, 0xb1, 0x76, 0xa4, 0x6f, 0x08, 0xb6, 0x0d, 0x7f, 0xb6, 0x43, 0x1a, 0x28, 0x9e,
0x40, 0x6f, 0xc9, 0x2d, 0xa7, 0x83, 0xe8, 0xd9, 0xff, 0xbb, 0x53, 0xcf, 0x76, 0x48, 0x0d, 0xe3,
0xf8, 0x98, 0xdf, 0xaa, 0xae, 0x3d, 0xc7, 0xb7, 0xdd, 0xc2, 0xf1, 0x02, 0x66, 0x7c, 0x07, 0xad,
0x35, 0x37, 0xd6, 0x61, 0xaf, 0xf1, 0x81, 0x6b, 0x87, 0x61, 0xcb, 0xd6, 0xbb, 0x00, 0xbe, 0x67,
0x47, 0xd4, 0x8f, 0x7c, 0xcf, 0x46, 0x12, 0x46, 0x30, 0x0c, 0x66, 0x27, 0x97, 0x8e, 0x15, 0x4d,
0x89, 0x3f, 0x0b, 0x50, 0x07, 0xbf, 0x84, 0x17, 0x01, 0x71, 0x3e, 0x9b, 0xd4, 0x7e, 0x2a, 0x75,
0xf1, 0x08, 0x0e, 0xc3, 0xeb, 0x90, 0xda, 0xee, 0x9a, 0x6d, 0x1b, 0x21, 0x1b, 0xbf, 0x24, 0xd0,
0x5a, 0x2b, 0x6b, 0x0b, 0xb0, 0x7c, 0x8f, 0xda, 0x1e, 0x6d, 0x09, 0xa0, 0xf6, 0x17, 0x1a, 0x05,
0x97, 0xa6, 0xe3, 0x21, 0x09, 0x6b, 0xa0, 0x84, 0xd4, 0xb1, 0x2e, 0x6c, 0x82, 0x3a, 0x18, 0xa0,
0x1f, 0x52, 0x93, 0xce, 0x42, 0xd4, 0xc5, 0x2a, 0xf4, 0x6c, 0xd7, 0x3f, 0x77, 0x90, 0x8c, 0x0f,
0xe0, 0x15, 0x25, 0xa6, 0x17, 0x9a, 0x16, 0x75, 0x7c, 0xce, 0xe8, 0xba, 0xa6, 0x77, 0x8a, 0x7a,
0x78, 0x0c, 0xef, 0x9e, 0x09, 0x6b, 0xfe, 0xb6, 0x2d, 0xb0, 0xcf, 0xd9, 0xc4, 0xf3, 0x46, 0x0a,
0x0f, 0xc5, 0xe3, 0x40, 0x83, 0x13, 0x75, 0xfd, 0x5a, 0x6f, 0xfa, 0x62, 0xc3, 0xef, 0xff, 0x04,
0x00, 0x00, 0xff, 0xff, 0x5b, 0xc2, 0xb0, 0xfc, 0xd6, 0x04, 0x00, 0x00,
// 618 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x53, 0x4f, 0x6f, 0x9b, 0x4e,
0x10, 0x0d, 0x36, 0x18, 0x33, 0x58, 0xd1, 0x6a, 0x7f, 0xf9, 0x25, 0xb4, 0xaa, 0x54, 0x17, 0xf5,
0xe0, 0x93, 0x0f, 0x69, 0x2a, 0xe5, 0x4a, 0x1c, 0xea, 0x90, 0x14, 0x8c, 0x96, 0x75, 0xd3, 0x9c,
0x10, 0xc1, 0xdb, 0xd8, 0x4a, 0xf8, 0x23, 0xb3, 0x96, 0x9a, 0x6b, 0xbf, 0x4d, 0xef, 0x55, 0x3f,
0x5f, 0xb5, 0x4b, 0x08, 0xb4, 0xea, 0xad, 0x27, 0x66, 0x66, 0xdf, 0x5b, 0xde, 0xcc, 0xbc, 0x05,
0x9c, 0xae, 0x13, 0x1e, 0x67, 0xac, 0xaa, 0x92, 0x3b, 0x36, 0x2d, 0xb7, 0x05, 0x2f, 0xf0, 0x50,
0x7e, 0x6e, 0x77, 0x5f, 0x5e, 0x9a, 0x2c, 0xdf, 0x65, 0x55, 0x5d, 0xb6, 0x4f, 0x61, 0x3f, 0xe2,
0x9b, 0xf4, 0x9e, 0x6d, 0xfd, 0x1a, 0x8e, 0x31, 0xa8, 0xeb, 0xa4, 0x5a, 0x5b, 0xca, 0x58, 0x99,
0x18, 0x44, 0xc6, 0xa2, 0x56, 0x26, 0xe9, 0xbd, 0xd5, 0x1b, 0x2b, 0x13, 0x8d, 0xc8, 0xd8, 0xfe,
0xae, 0xc0, 0xc8, 0xcb, 0x92, 0x3b, 0xd6, 0x10, 0x2d, 0xd0, 0xcb, 0xe4, 0xf1, 0xa1, 0x48, 0x56,
0x92, 0x3b, 0x22, 0x4d, 0x8a, 0x4f, 0x40, 0xe5, 0x8f, 0x25, 0x93, 0xf4, 0xfd, 0xe3, 0xf1, 0xb4,
0x91, 0x32, 0xed, 0xf2, 0xeb, 0x84, 0x3e, 0x96, 0x8c, 0x48, 0xb4, 0xed, 0x81, 0xf1, 0x5c, 0xc2,
0x87, 0x80, 0x97, 0xc1, 0x55, 0xb0, 0xb8, 0x0e, 0x62, 0xcf, 0x77, 0xe6, 0x6e, 0x4c, 0x6f, 0x42,
0x17, 0xed, 0x61, 0x1d, 0xfa, 0x61, 0x30, 0x47, 0x0a, 0x1e, 0x82, 0x7a, 0x19, 0xba, 0x73, 0xd4,
0x13, 0xd1, 0xb5, 0x7b, 0x16, 0xa2, 0xbe, 0x38, 0x9c, 0x7b, 0x1f, 0x90, 0x6a, 0xff, 0x54, 0x60,
0xe4, 0xec, 0x56, 0x9b, 0xe2, 0x1f, 0xb4, 0x76, 0xf9, 0x75, 0xd2, 0x6a, 0xc5, 0xaf, 0xc1, 0x5c,
0xed, 0xb6, 0x09, 0xdf, 0x14, 0x79, 0x9c, 0x55, 0x56, 0x7f, 0xac, 0x4c, 0x54, 0x02, 0x4d, 0xc9,
0xaf, 0xec, 0xf7, 0x60, 0x3c, 0x73, 0xba, 0xcd, 0x38, 0xcb, 0x73, 0x6f, 0xd1, 0x69, 0xc6, 0x71,
0x66, 0x48, 0x91, 0x81, 0x4f, 0x50, 0xcf, 0xfe, 0xa6, 0x81, 0x39, 0x5b, 0x27, 0xbc, 0xd1, 0x7d,
0x00, 0x5a, 0xfa, 0x50, 0xa4, 0xf7, 0x52, 0xb5, 0x4a, 0xea, 0x04, 0xbf, 0x02, 0x83, 0x6f, 0x32,
0x56, 0xf1, 0x24, 0x2b, 0xa5, 0x70, 0x95, 0xb4, 0x05, 0xb1, 0x3c, 0xce, 0xbe, 0x72, 0x29, 0xca,
0x20, 0x32, 0x16, 0x7a, 0xb7, 0xac, 0x2a, 0x8b, 0xbc, 0x62, 0x31, 0x2f, 0x2c, 0x55, 0x1e, 0x41,
0x53, 0xa2, 0x05, 0x7e, 0x01, 0x43, 0x96, 0x57, 0x71, 0x9e, 0x64, 0xcc, 0xd2, 0xe4, 0xa9, 0xce,
0xf2, 0x2a, 0x48, 0x32, 0x86, 0x8f, 0x40, 0x97, 0xfe, 0xda, 0xac, 0xac, 0x81, 0x3c, 0x19, 0x88,
0xd4, 0x5b, 0xe1, 0x53, 0x18, 0x3d, 0x79, 0x2e, 0x96, 0x23, 0xd4, 0xe5, 0x08, 0xff, 0x6f, 0x47,
0xf8, 0xd4, 0x85, 0x9c, 0x9b, 0x99, 0xb5, 0x09, 0x3e, 0x87, 0x51, 0x5a, 0xe4, 0x9c, 0xe5, 0xbc,
0x66, 0x0e, 0x25, 0xf3, 0x4d, 0xcb, 0xec, 0xcc, 0x60, 0x3a, 0xab, 0x91, 0xf5, 0x2d, 0x69, 0x9b,
0xe0, 0x13, 0xd0, 0xab, 0xda, 0xcb, 0x96, 0x31, 0x56, 0x26, 0xe6, 0xb1, 0xd5, 0x5e, 0xf0, 0xbb,
0xc9, 0x2f, 0xf6, 0x48, 0x03, 0xc5, 0x53, 0xd0, 0x36, 0xc2, 0x66, 0x16, 0x48, 0xce, 0xe1, 0xdf,
0xdd, 0x79, 0xb1, 0x47, 0x6a, 0x98, 0xc0, 0x27, 0x62, 0x93, 0x96, 0xf9, 0x27, 0xbe, 0xeb, 0x10,
0x81, 0x97, 0x30, 0xfb, 0x87, 0x02, 0x66, 0x47, 0x32, 0xb6, 0xe0, 0xa0, 0x59, 0xfe, 0x6c, 0x11,
0x50, 0x37, 0xa0, 0xcd, 0xfa, 0xf7, 0x01, 0xa8, 0xfb, 0x99, 0xc6, 0xe1, 0x47, 0xc7, 0x0b, 0x90,
0x82, 0x4d, 0xd0, 0x23, 0xea, 0xcd, 0xae, 0x5c, 0x82, 0x7a, 0x18, 0x60, 0x10, 0x51, 0x87, 0x2e,
0x23, 0xd4, 0xc7, 0x06, 0x68, 0xae, 0xbf, 0xb8, 0xf4, 0x90, 0x8a, 0x8f, 0xe0, 0x3f, 0x4a, 0x9c,
0x20, 0x72, 0x66, 0xd4, 0x5b, 0x88, 0x1b, 0x7d, 0xdf, 0x09, 0xce, 0x91, 0x86, 0x27, 0xf0, 0x36,
0xba, 0x89, 0xa8, 0xeb, 0xc7, 0xbe, 0x1b, 0x45, 0xe2, 0xc5, 0x34, 0x7f, 0x0b, 0x89, 0xf7, 0xc9,
0xa1, 0x6e, 0x3c, 0x27, 0x8b, 0x65, 0x88, 0x06, 0xe2, 0x36, 0xf9, 0xa4, 0x90, 0x2e, 0x42, 0x69,
0x48, 0x34, 0x3c, 0x33, 0x9e, 0x5f, 0xc8, 0xed, 0x40, 0x76, 0xf8, 0xee, 0x57, 0x00, 0x00, 0x00,
0xff, 0xff, 0xef, 0xa1, 0x83, 0xb2, 0x57, 0x04, 0x00, 0x00,
}

View File

@ -2,6 +2,8 @@ syntax = "proto3";
package protobuf;
import "enums.proto";
message StickerMessage {
string hash = 1;
int32 pack = 2;
@ -59,13 +61,6 @@ message ChatMessage {
AudioMessage audio = 11;
}
enum MessageType {
UNKNOWN_MESSAGE_TYPE = 0;
ONE_TO_ONE = 1;
PUBLIC_GROUP = 2;
PRIVATE_GROUP = 3;
// Only local
SYSTEM_MESSAGE_PRIVATE_GROUP = 4;}
enum ContentType {
UNKNOWN_CONTENT_TYPE = 0;
TEXT_PLAIN = 1;

View File

@ -0,0 +1,178 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: emoji_reaction.proto
package protobuf
import (
fmt "fmt"
proto "github.com/golang/protobuf/proto"
math "math"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
type EmojiReaction_Type int32
const (
EmojiReaction_UNKNOWN_EMOJI_REACTION_TYPE EmojiReaction_Type = 0
EmojiReaction_LOVE EmojiReaction_Type = 1
EmojiReaction_THUMBS_UP EmojiReaction_Type = 2
EmojiReaction_THUMBS_DOWN EmojiReaction_Type = 3
EmojiReaction_LAUGH EmojiReaction_Type = 4
EmojiReaction_SAD EmojiReaction_Type = 5
EmojiReaction_ANGRY EmojiReaction_Type = 6
)
var EmojiReaction_Type_name = map[int32]string{
0: "UNKNOWN_EMOJI_REACTION_TYPE",
1: "LOVE",
2: "THUMBS_UP",
3: "THUMBS_DOWN",
4: "LAUGH",
5: "SAD",
6: "ANGRY",
}
var EmojiReaction_Type_value = map[string]int32{
"UNKNOWN_EMOJI_REACTION_TYPE": 0,
"LOVE": 1,
"THUMBS_UP": 2,
"THUMBS_DOWN": 3,
"LAUGH": 4,
"SAD": 5,
"ANGRY": 6,
}
func (x EmojiReaction_Type) String() string {
return proto.EnumName(EmojiReaction_Type_name, int32(x))
}
func (EmojiReaction_Type) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_0a088c907bbc7ed6, []int{0, 0}
}
type EmojiReaction struct {
// clock Lamport timestamp of the chat message
Clock uint64 `protobuf:"varint,1,opt,name=clock,proto3" json:"clock,omitempty"`
// chat_id the ID of the chat the message belongs to, for query efficiency the chat_id is stored in the db even though the
// target message also stores the chat_id
ChatId string `protobuf:"bytes,2,opt,name=chat_id,json=chatId,proto3" json:"chat_id,omitempty"`
// message_id the ID of the target message that the user wishes to react to
MessageId string `protobuf:"bytes,3,opt,name=message_id,json=messageId,proto3" json:"message_id,omitempty"`
// message_type is (somewhat confusingly) the ID of the type of chat the message belongs to
MessageType MessageType `protobuf:"varint,4,opt,name=message_type,json=messageType,proto3,enum=protobuf.MessageType" json:"message_type,omitempty"`
// type the ID of the emoji the user wishes to react with
Type EmojiReaction_Type `protobuf:"varint,5,opt,name=type,proto3,enum=protobuf.EmojiReaction_Type" json:"type,omitempty"`
// whether this is a rectraction of a previously sent emoji
Retracted bool `protobuf:"varint,6,opt,name=retracted,proto3" json:"retracted,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *EmojiReaction) Reset() { *m = EmojiReaction{} }
func (m *EmojiReaction) String() string { return proto.CompactTextString(m) }
func (*EmojiReaction) ProtoMessage() {}
func (*EmojiReaction) Descriptor() ([]byte, []int) {
return fileDescriptor_0a088c907bbc7ed6, []int{0}
}
func (m *EmojiReaction) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_EmojiReaction.Unmarshal(m, b)
}
func (m *EmojiReaction) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_EmojiReaction.Marshal(b, m, deterministic)
}
func (m *EmojiReaction) XXX_Merge(src proto.Message) {
xxx_messageInfo_EmojiReaction.Merge(m, src)
}
func (m *EmojiReaction) XXX_Size() int {
return xxx_messageInfo_EmojiReaction.Size(m)
}
func (m *EmojiReaction) XXX_DiscardUnknown() {
xxx_messageInfo_EmojiReaction.DiscardUnknown(m)
}
var xxx_messageInfo_EmojiReaction proto.InternalMessageInfo
func (m *EmojiReaction) GetClock() uint64 {
if m != nil {
return m.Clock
}
return 0
}
func (m *EmojiReaction) GetChatId() string {
if m != nil {
return m.ChatId
}
return ""
}
func (m *EmojiReaction) GetMessageId() string {
if m != nil {
return m.MessageId
}
return ""
}
func (m *EmojiReaction) GetMessageType() MessageType {
if m != nil {
return m.MessageType
}
return MessageType_UNKNOWN_MESSAGE_TYPE
}
func (m *EmojiReaction) GetType() EmojiReaction_Type {
if m != nil {
return m.Type
}
return EmojiReaction_UNKNOWN_EMOJI_REACTION_TYPE
}
func (m *EmojiReaction) GetRetracted() bool {
if m != nil {
return m.Retracted
}
return false
}
func init() {
proto.RegisterEnum("protobuf.EmojiReaction_Type", EmojiReaction_Type_name, EmojiReaction_Type_value)
proto.RegisterType((*EmojiReaction)(nil), "protobuf.EmojiReaction")
}
func init() { proto.RegisterFile("emoji_reaction.proto", fileDescriptor_0a088c907bbc7ed6) }
var fileDescriptor_0a088c907bbc7ed6 = []byte{
// 305 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x54, 0x8e, 0xdf, 0x4f, 0x82, 0x50,
0x14, 0xc7, 0x43, 0x01, 0xe5, 0x98, 0x75, 0x77, 0x66, 0x8b, 0x95, 0x2d, 0xe6, 0x13, 0x4f, 0xac,
0xd5, 0x4b, 0xaf, 0x94, 0x4c, 0x29, 0x05, 0x77, 0x85, 0x9c, 0x4f, 0x0c, 0xe1, 0x56, 0x56, 0x08,
0xc3, 0xeb, 0x83, 0x7f, 0x6a, 0xff, 0x4d, 0xe3, 0xaa, 0x73, 0x3d, 0x9d, 0x7d, 0x7f, 0x7c, 0xce,
0xbe, 0xd0, 0x61, 0x59, 0xfe, 0xb5, 0x8c, 0x4a, 0x16, 0x27, 0x7c, 0x99, 0xaf, 0xac, 0xa2, 0xcc,
0x79, 0x8e, 0x4d, 0x71, 0x16, 0x9b, 0xf7, 0xab, 0x16, 0x5b, 0x6d, 0xb2, 0xf5, 0xce, 0xee, 0xfd,
0xd6, 0xa0, 0xed, 0x54, 0x7d, 0xba, 0xaf, 0x63, 0x07, 0x94, 0xe4, 0x27, 0x4f, 0xbe, 0x75, 0xc9,
0x90, 0x4c, 0x99, 0xee, 0x04, 0x5e, 0x42, 0x23, 0xf9, 0x8c, 0x79, 0xb4, 0x4c, 0xf5, 0x9a, 0x21,
0x99, 0x1a, 0x55, 0x2b, 0xe9, 0xa6, 0x78, 0x03, 0x90, 0xb1, 0xf5, 0x3a, 0xfe, 0x60, 0x55, 0x56,
0x17, 0x99, 0xb6, 0x77, 0xdc, 0x14, 0x1f, 0xe1, 0xf4, 0x10, 0xf3, 0x6d, 0xc1, 0x74, 0xd9, 0x90,
0xcc, 0xb3, 0xfb, 0x0b, 0xeb, 0xb0, 0xc6, 0x1a, 0xef, 0xd2, 0x60, 0x5b, 0x30, 0xda, 0xca, 0x8e,
0x02, 0xef, 0x40, 0x16, 0x84, 0x22, 0x88, 0xee, 0x91, 0xf8, 0x37, 0xd7, 0x12, 0xa0, 0x68, 0x62,
0x17, 0xb4, 0x92, 0xf1, 0x32, 0x4e, 0x38, 0x4b, 0x75, 0xd5, 0x90, 0xcc, 0x26, 0x3d, 0x1a, 0xbd,
0x02, 0x64, 0xf1, 0xf7, 0x16, 0xae, 0x43, 0xef, 0xd5, 0xf3, 0x67, 0x5e, 0xe4, 0x8c, 0xfd, 0x17,
0x37, 0xa2, 0x8e, 0xfd, 0x1c, 0xb8, 0xbe, 0x17, 0x05, 0xf3, 0x89, 0x43, 0x4e, 0xb0, 0x09, 0xf2,
0xc8, 0x7f, 0x73, 0x88, 0x84, 0x6d, 0xd0, 0x82, 0x61, 0x38, 0x7e, 0x9a, 0x46, 0xe1, 0x84, 0xd4,
0xf0, 0x1c, 0x5a, 0x7b, 0xd9, 0xf7, 0x67, 0x1e, 0xa9, 0xa3, 0x06, 0xca, 0xc8, 0x0e, 0x07, 0x43,
0x22, 0x63, 0x03, 0xea, 0x53, 0xbb, 0x4f, 0x94, 0xca, 0xb3, 0xbd, 0x01, 0x9d, 0x13, 0x75, 0xa1,
0x8a, 0xc9, 0x0f, 0x7f, 0x01, 0x00, 0x00, 0xff, 0xff, 0x03, 0x65, 0x6e, 0x92, 0x91, 0x01, 0x00,
0x00,
}

View File

@ -0,0 +1,36 @@
syntax = "proto3";
package protobuf;
import "enums.proto";
message EmojiReaction {
// clock Lamport timestamp of the chat message
uint64 clock = 1;
// chat_id the ID of the chat the message belongs to, for query efficiency the chat_id is stored in the db even though the
// target message also stores the chat_id
string chat_id = 2;
// message_id the ID of the target message that the user wishes to react to
string message_id = 3;
// message_type is (somewhat confusingly) the ID of the type of chat the message belongs to
MessageType message_type = 4;
// type the ID of the emoji the user wishes to react with
Type type = 5;
enum Type {
UNKNOWN_EMOJI_REACTION_TYPE = 0;
LOVE = 1;
THUMBS_UP = 2;
THUMBS_DOWN = 3;
LAUGH = 4;
SAD = 5;
ANGRY = 6;
}
// whether this is a rectraction of a previously sent emoji
bool retracted = 6;
}

View File

@ -0,0 +1,76 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: enums.proto
package protobuf
import (
fmt "fmt"
proto "github.com/golang/protobuf/proto"
math "math"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
type MessageType int32
const (
MessageType_UNKNOWN_MESSAGE_TYPE MessageType = 0
MessageType_ONE_TO_ONE MessageType = 1
MessageType_PUBLIC_GROUP MessageType = 2
MessageType_PRIVATE_GROUP MessageType = 3
// Only local
MessageType_SYSTEM_MESSAGE_PRIVATE_GROUP MessageType = 4
)
var MessageType_name = map[int32]string{
0: "UNKNOWN_MESSAGE_TYPE",
1: "ONE_TO_ONE",
2: "PUBLIC_GROUP",
3: "PRIVATE_GROUP",
4: "SYSTEM_MESSAGE_PRIVATE_GROUP",
}
var MessageType_value = map[string]int32{
"UNKNOWN_MESSAGE_TYPE": 0,
"ONE_TO_ONE": 1,
"PUBLIC_GROUP": 2,
"PRIVATE_GROUP": 3,
"SYSTEM_MESSAGE_PRIVATE_GROUP": 4,
}
func (x MessageType) String() string {
return proto.EnumName(MessageType_name, int32(x))
}
func (MessageType) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_888b6bd9597961ff, []int{0}
}
func init() {
proto.RegisterEnum("protobuf.MessageType", MessageType_name, MessageType_value)
}
func init() { proto.RegisterFile("enums.proto", fileDescriptor_888b6bd9597961ff) }
var fileDescriptor_888b6bd9597961ff = []byte{
// 153 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x4e, 0xcd, 0x2b, 0xcd,
0x2d, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x00, 0x53, 0x49, 0xa5, 0x69, 0x5a, 0x75,
0x5c, 0xdc, 0xbe, 0xa9, 0xc5, 0xc5, 0x89, 0xe9, 0xa9, 0x21, 0x95, 0x05, 0xa9, 0x42, 0x12, 0x5c,
0x22, 0xa1, 0x7e, 0xde, 0x7e, 0xfe, 0xe1, 0x7e, 0xf1, 0xbe, 0xae, 0xc1, 0xc1, 0x8e, 0xee, 0xae,
0xf1, 0x21, 0x91, 0x01, 0xae, 0x02, 0x0c, 0x42, 0x7c, 0x5c, 0x5c, 0xfe, 0x7e, 0xae, 0xf1, 0x21,
0xfe, 0xf1, 0xfe, 0x7e, 0xae, 0x02, 0x8c, 0x42, 0x02, 0x5c, 0x3c, 0x01, 0xa1, 0x4e, 0x3e, 0x9e,
0xce, 0xf1, 0xee, 0x41, 0xfe, 0xa1, 0x01, 0x02, 0x4c, 0x42, 0x82, 0x5c, 0xbc, 0x01, 0x41, 0x9e,
0x61, 0x8e, 0x21, 0xae, 0x50, 0x21, 0x66, 0x21, 0x05, 0x2e, 0x99, 0xe0, 0xc8, 0xe0, 0x10, 0x57,
0x5f, 0xb8, 0x69, 0xa8, 0x2a, 0x58, 0x92, 0xd8, 0xc0, 0x2e, 0x31, 0x06, 0x04, 0x00, 0x00, 0xff,
0xff, 0xa7, 0x40, 0x6b, 0x1d, 0x9f, 0x00, 0x00, 0x00,
}

View File

@ -0,0 +1,12 @@
syntax = "proto3";
package protobuf;
enum MessageType {
UNKNOWN_MESSAGE_TYPE = 0;
ONE_TO_ONE = 1;
PUBLIC_GROUP = 2;
PRIVATE_GROUP = 3;
// Only local
SYSTEM_MESSAGE_PRIVATE_GROUP = 4;
}

View File

@ -140,10 +140,14 @@ type MembershipUpdateMessage struct {
// protobuf encoded MembershipUpdateEvent
Events [][]byte `protobuf:"bytes,2,rep,name=events,proto3" json:"events,omitempty"`
// An optional chat message
Message *ChatMessage `protobuf:"bytes,3,opt,name=message,proto3" json:"message,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
//
// Types that are valid to be assigned to ChatEntity:
// *MembershipUpdateMessage_Message
// *MembershipUpdateMessage_EmojiReaction
ChatEntity isMembershipUpdateMessage_ChatEntity `protobuf_oneof:"chat_entity"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *MembershipUpdateMessage) Reset() { *m = MembershipUpdateMessage{} }
@ -185,13 +189,51 @@ func (m *MembershipUpdateMessage) GetEvents() [][]byte {
return nil
}
func (m *MembershipUpdateMessage) GetMessage() *ChatMessage {
type isMembershipUpdateMessage_ChatEntity interface {
isMembershipUpdateMessage_ChatEntity()
}
type MembershipUpdateMessage_Message struct {
Message *ChatMessage `protobuf:"bytes,3,opt,name=message,proto3,oneof"`
}
type MembershipUpdateMessage_EmojiReaction struct {
EmojiReaction *EmojiReaction `protobuf:"bytes,4,opt,name=emoji_reaction,json=emojiReaction,proto3,oneof"`
}
func (*MembershipUpdateMessage_Message) isMembershipUpdateMessage_ChatEntity() {}
func (*MembershipUpdateMessage_EmojiReaction) isMembershipUpdateMessage_ChatEntity() {}
func (m *MembershipUpdateMessage) GetChatEntity() isMembershipUpdateMessage_ChatEntity {
if m != nil {
return m.Message
return m.ChatEntity
}
return nil
}
func (m *MembershipUpdateMessage) GetMessage() *ChatMessage {
if x, ok := m.GetChatEntity().(*MembershipUpdateMessage_Message); ok {
return x.Message
}
return nil
}
func (m *MembershipUpdateMessage) GetEmojiReaction() *EmojiReaction {
if x, ok := m.GetChatEntity().(*MembershipUpdateMessage_EmojiReaction); ok {
return x.EmojiReaction
}
return nil
}
// XXX_OneofWrappers is for the internal use of the proto package.
func (*MembershipUpdateMessage) XXX_OneofWrappers() []interface{} {
return []interface{}{
(*MembershipUpdateMessage_Message)(nil),
(*MembershipUpdateMessage_EmojiReaction)(nil),
}
}
func init() {
proto.RegisterEnum("protobuf.MembershipUpdateEvent_EventType", MembershipUpdateEvent_EventType_name, MembershipUpdateEvent_EventType_value)
proto.RegisterType((*MembershipUpdateEvent)(nil), "protobuf.MembershipUpdateEvent")
@ -201,27 +243,30 @@ func init() {
func init() { proto.RegisterFile("membership_update_message.proto", fileDescriptor_8d37dd0dc857a6be) }
var fileDescriptor_8d37dd0dc857a6be = []byte{
// 340 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x50, 0x41, 0x4f, 0xf2, 0x40,
0x10, 0xfd, 0x0a, 0xa5, 0xfd, 0x3a, 0x20, 0xa9, 0x13, 0x91, 0xc6, 0x8b, 0x0d, 0xa7, 0x7a, 0xa9,
0x09, 0x9e, 0x3d, 0xd4, 0xee, 0x46, 0xd0, 0xec, 0x92, 0xac, 0xa0, 0xc7, 0xa6, 0xc0, 0x2a, 0x44,
0x0b, 0x0d, 0x14, 0x13, 0xe2, 0x4f, 0xf1, 0x8f, 0xf8, 0xf3, 0x4c, 0x97, 0x16, 0xa2, 0xf1, 0xb2,
0xbb, 0xef, 0xcd, 0xbc, 0x37, 0x3b, 0x0f, 0xce, 0x13, 0x99, 0x8c, 0xe5, 0x6a, 0x3d, 0x9b, 0xa7,
0xd1, 0x26, 0x9d, 0xc6, 0x99, 0x8c, 0x12, 0xb9, 0x5e, 0xc7, 0x2f, 0xd2, 0x4f, 0x57, 0xcb, 0x6c,
0x89, 0xff, 0xd5, 0x35, 0xde, 0x3c, 0x9f, 0xe1, 0x64, 0x16, 0x67, 0x3f, 0xab, 0x9d, 0xaf, 0x0a,
0xb4, 0xd8, 0xde, 0x61, 0xa4, 0x0c, 0xe8, 0xbb, 0x5c, 0x64, 0x78, 0x02, 0xb5, 0xc9, 0xdb, 0x72,
0xf2, 0xea, 0x68, 0xae, 0xe6, 0xe9, 0x62, 0x07, 0xd0, 0x01, 0xb3, 0x18, 0xe8, 0x54, 0xdc, 0xaa,
0x67, 0x89, 0x12, 0x22, 0x82, 0xbe, 0x88, 0x13, 0xe9, 0x54, 0x5d, 0xcd, 0xb3, 0x84, 0x7a, 0xe3,
0x35, 0xe8, 0xd9, 0x36, 0x95, 0x8e, 0xee, 0x6a, 0x5e, 0xb3, 0x7b, 0xe1, 0x97, 0x5f, 0xf1, 0xff,
0x1c, 0xe9, 0xab, 0x73, 0xb8, 0x4d, 0xa5, 0x50, 0xb2, 0xce, 0xa7, 0x06, 0xd6, 0x9e, 0xc3, 0x3a,
0x98, 0x23, 0x7e, 0xcf, 0x07, 0x4f, 0xdc, 0xfe, 0x87, 0x36, 0x34, 0xc2, 0x5e, 0x30, 0x8c, 0x42,
0x41, 0x83, 0x21, 0x25, 0xb6, 0x96, 0x33, 0x3c, 0x60, 0x34, 0x0a, 0x7b, 0x01, 0xbf, 0xa5, 0xc4,
0xae, 0xe0, 0x31, 0x1c, 0x31, 0xca, 0x6e, 0xa8, 0x78, 0x88, 0x02, 0x42, 0x28, 0xb1, 0xab, 0x07,
0x2a, 0xba, 0x1b, 0xf4, 0x39, 0x25, 0xb6, 0x8e, 0x08, 0xcd, 0x82, 0x12, 0x94, 0x0d, 0x1e, 0x29,
0xb1, 0x6b, 0xb9, 0x57, 0x40, 0x58, 0x9f, 0x97, 0x42, 0x23, 0x17, 0x2a, 0x66, 0xdf, 0x64, 0x76,
0x3e, 0xa0, 0xfd, 0x7b, 0x0d, 0xb6, 0xcb, 0x16, 0xdb, 0x60, 0xaa, 0xac, 0xe7, 0x53, 0x95, 0x9e,
0x25, 0x8c, 0x1c, 0xf6, 0xa7, 0x78, 0x0a, 0x86, 0xcc, 0x17, 0xda, 0xa5, 0xd7, 0x10, 0x05, 0xc2,
0xcb, 0x3c, 0x56, 0xa5, 0x55, 0xf9, 0xd5, 0xbb, 0xad, 0x43, 0x56, 0xe1, 0x2c, 0xce, 0x0a, 0x63,
0x51, 0x76, 0x8d, 0x0d, 0x55, 0xbe, 0xfa, 0x0e, 0x00, 0x00, 0xff, 0xff, 0x7f, 0xb8, 0xe8, 0x9e,
0xff, 0x01, 0x00, 0x00,
// 393 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x51, 0x4d, 0xaf, 0x93, 0x50,
0x10, 0x2d, 0x2d, 0x0f, 0x64, 0x78, 0x6d, 0x70, 0xf2, 0x9e, 0x25, 0x6f, 0x23, 0xe9, 0x0a, 0x37,
0x24, 0xd6, 0xb5, 0x89, 0x3c, 0xee, 0x8d, 0x54, 0x03, 0x4d, 0xae, 0xad, 0x2e, 0x09, 0xa5, 0x57,
0x8b, 0xca, 0x47, 0xda, 0x5b, 0x93, 0xfe, 0x16, 0xff, 0x88, 0xbf, 0xc2, 0xdf, 0x64, 0xb8, 0x40,
0x6b, 0x8d, 0x1b, 0xe0, 0x9c, 0x99, 0x73, 0x98, 0x39, 0x03, 0xcf, 0x0b, 0x5e, 0x6c, 0xf8, 0xfe,
0xb0, 0xcb, 0xeb, 0xe4, 0x58, 0x6f, 0x53, 0xc1, 0x93, 0x82, 0x1f, 0x0e, 0xe9, 0x17, 0xee, 0xd5,
0xfb, 0x4a, 0x54, 0xf8, 0x44, 0xbe, 0x36, 0xc7, 0xcf, 0x0f, 0x98, 0xed, 0x52, 0x71, 0x5d, 0x7d,
0xb8, 0xe3, 0x45, 0xf5, 0x35, 0x4f, 0xf6, 0x3c, 0xcd, 0x44, 0x5e, 0x95, 0x2d, 0x3b, 0xfb, 0x35,
0x84, 0xfb, 0xe8, 0xec, 0xbb, 0x96, 0xb6, 0xf4, 0x07, 0x2f, 0x05, 0xde, 0xc1, 0x4d, 0xf6, 0xbd,
0xca, 0xbe, 0xd9, 0x8a, 0xa3, 0xb8, 0x2a, 0x6b, 0x01, 0xda, 0xa0, 0x77, 0x63, 0xd8, 0x43, 0x67,
0xe4, 0x1a, 0xac, 0x87, 0x88, 0xa0, 0x96, 0x69, 0xc1, 0xed, 0x91, 0xa3, 0xb8, 0x06, 0x93, 0xdf,
0xf8, 0x1a, 0x54, 0x71, 0xaa, 0xb9, 0xad, 0x3a, 0x8a, 0x3b, 0x99, 0xbf, 0xf0, 0xfa, 0x01, 0xbd,
0xff, 0xfe, 0xd2, 0x93, 0xcf, 0xd5, 0xa9, 0xe6, 0x4c, 0xca, 0x66, 0x3f, 0x15, 0x30, 0xce, 0x1c,
0x9a, 0xa0, 0xaf, 0xe3, 0xf7, 0xf1, 0xf2, 0x53, 0x6c, 0x0d, 0xd0, 0x82, 0xdb, 0x20, 0xf4, 0x57,
0x49, 0xc0, 0xa8, 0xbf, 0xa2, 0xc4, 0x52, 0x1a, 0x26, 0xf6, 0x23, 0x9a, 0x04, 0xa1, 0x1f, 0xbf,
0xa5, 0xc4, 0x1a, 0xe2, 0x53, 0x18, 0x47, 0x34, 0x7a, 0xa4, 0xec, 0x43, 0xe2, 0x13, 0x42, 0x89,
0x35, 0xba, 0x50, 0xc9, 0xbb, 0xe5, 0x22, 0xa6, 0xc4, 0x52, 0x11, 0x61, 0xd2, 0x51, 0x8c, 0x46,
0xcb, 0x8f, 0x94, 0x58, 0x37, 0x8d, 0x97, 0x4f, 0xa2, 0x45, 0xdc, 0x0b, 0xb5, 0x46, 0x28, 0x99,
0x73, 0x93, 0x3e, 0xfb, 0xad, 0xc0, 0xf4, 0xdf, 0x3d, 0xa2, 0x36, 0x72, 0x9c, 0x82, 0x2e, 0x4f,
0x90, 0x6f, 0x65, 0x7c, 0x06, 0xd3, 0x1a, 0xb8, 0xd8, 0xe2, 0x33, 0xd0, 0x78, 0xb3, 0x51, 0x1b,
0xdf, 0x2d, 0xeb, 0x10, 0xbe, 0x6c, 0x72, 0x95, 0x5a, 0x19, 0xa0, 0x39, 0xbf, 0xbf, 0x84, 0x15,
0xec, 0x52, 0xd1, 0x19, 0x87, 0x03, 0xd6, 0xf7, 0xe1, 0x1b, 0x98, 0x5c, 0x9f, 0x54, 0xc6, 0x6c,
0xce, 0xa7, 0x17, 0x25, 0x6d, 0xea, 0xac, 0x2b, 0x87, 0x03, 0x36, 0xe6, 0x7f, 0x13, 0x8f, 0x63,
0x30, 0xe5, 0x94, 0xbc, 0x14, 0xb9, 0x38, 0x6d, 0x34, 0xa9, 0x7b, 0xf5, 0x27, 0x00, 0x00, 0xff,
0xff, 0x77, 0x9d, 0x8d, 0xe2, 0x69, 0x02, 0x00, 0x00,
}

View File

@ -3,6 +3,7 @@ syntax = "proto3";
package protobuf;
import "chat_message.proto";
import "emoji_reaction.proto";
message MembershipUpdateEvent {
// Lamport timestamp of the event
@ -35,6 +36,10 @@ message MembershipUpdateMessage {
// A list of events for this group chat, first x bytes are the signature, then is a
// protobuf encoded MembershipUpdateEvent
repeated bytes events = 2;
// An optional chat message
ChatMessage message = 3;
oneof chat_entity {
ChatMessage message = 3;
EmojiReaction emoji_reaction = 4;
}
}

View File

@ -4,7 +4,7 @@ import (
"github.com/golang/protobuf/proto"
)
//go:generate protoc --go_out=. ./chat_message.proto ./application_metadata_message.proto ./membership_update_message.proto ./command.proto ./contact.proto ./pairing.proto ./push_notifications.proto
//go:generate protoc --go_out=. ./chat_message.proto ./application_metadata_message.proto ./membership_update_message.proto ./command.proto ./contact.proto ./pairing.proto ./push_notifications.proto ./emoji_reaction.proto ./enums.proto
func Unmarshal(payload []byte) (*ApplicationMetadataMessage, error) {
var message ApplicationMetadataMessage

View File

@ -86,7 +86,7 @@ func _1593601729_initial_schemaDownSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1593601729_initial_schema.down.sql", size: 144, mode: os.FileMode(0644), modTime: time.Unix(1595832279, 0)}
info := bindataFileInfo{name: "1593601729_initial_schema.down.sql", size: 144, mode: os.FileMode(0644), modTime: time.Unix(1595840384, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xa, 0x95, 0x55, 0x64, 0x38, 0x40, 0x16, 0xbf, 0x8b, 0x1c, 0x18, 0xb4, 0xc5, 0x7f, 0xd0, 0xb8, 0xf0, 0x3c, 0xa2, 0x82, 0xf8, 0x8d, 0x5a, 0xd3, 0xb6, 0x6e, 0xa3, 0xb4, 0xc, 0x9, 0x33, 0x0}}
return a, nil
}
@ -106,7 +106,7 @@ func _1593601729_initial_schemaUpSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1593601729_initial_schema.up.sql", size: 1773, mode: os.FileMode(0644), modTime: time.Unix(1595832279, 0)}
info := bindataFileInfo{name: "1593601729_initial_schema.up.sql", size: 1773, mode: os.FileMode(0644), modTime: time.Unix(1595840384, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x4e, 0x1e, 0x5, 0x35, 0x9, 0xb2, 0x2d, 0x6f, 0x33, 0x63, 0xa2, 0x7a, 0x5b, 0xd2, 0x2d, 0xcb, 0x79, 0x7e, 0x6, 0xb4, 0x9d, 0x35, 0xd8, 0x9b, 0x55, 0xe5, 0xf8, 0x44, 0xca, 0xa6, 0xf3, 0xd3}}
return a, nil
}
@ -126,7 +126,7 @@ func docGo() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "doc.go", size: 382, mode: os.FileMode(0644), modTime: time.Unix(1595832279, 0)}
info := bindataFileInfo{name: "doc.go", size: 382, mode: os.FileMode(0644), modTime: time.Unix(1595840384, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xc0, 0x2f, 0x1e, 0x64, 0x9, 0x93, 0xe4, 0x8b, 0xf2, 0x98, 0x5a, 0x45, 0xe2, 0x80, 0x88, 0x67, 0x7a, 0x2d, 0xd7, 0x4b, 0xd1, 0x73, 0xb6, 0x6d, 0x15, 0xc2, 0x0, 0x34, 0xcd, 0xa0, 0xdb, 0x20}}
return a, nil
}

View File

@ -86,7 +86,7 @@ func _1593601728_initial_schemaDownSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1593601728_initial_schema.down.sql", size: 200, mode: os.FileMode(0644), modTime: time.Unix(1595832279, 0)}
info := bindataFileInfo{name: "1593601728_initial_schema.down.sql", size: 200, mode: os.FileMode(0644), modTime: time.Unix(1595840384, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x88, 0x8a, 0x61, 0x81, 0x57, 0x45, 0x9b, 0x97, 0x9b, 0x1f, 0xf6, 0x94, 0x8a, 0x20, 0xb3, 0x2b, 0xff, 0x69, 0x49, 0xf4, 0x58, 0xcc, 0xd0, 0x55, 0xcc, 0x9a, 0x8b, 0xb6, 0x7f, 0x29, 0x53, 0xc1}}
return a, nil
}
@ -106,7 +106,7 @@ func _1593601728_initial_schemaUpSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1593601728_initial_schema.up.sql", size: 675, mode: os.FileMode(0644), modTime: time.Unix(1595832279, 0)}
info := bindataFileInfo{name: "1593601728_initial_schema.up.sql", size: 675, mode: os.FileMode(0644), modTime: time.Unix(1595840384, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xfd, 0x61, 0x90, 0x79, 0xd9, 0x14, 0x65, 0xe9, 0x96, 0x53, 0x17, 0x33, 0x54, 0xeb, 0x8b, 0x5d, 0x95, 0x99, 0x10, 0x36, 0x58, 0xdd, 0xb2, 0xbf, 0x45, 0xd9, 0xbb, 0xc4, 0x92, 0xe, 0xce, 0x2}}
return a, nil
}
@ -126,7 +126,7 @@ func docGo() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "doc.go", size: 382, mode: os.FileMode(0644), modTime: time.Unix(1595832279, 0)}
info := bindataFileInfo{name: "doc.go", size: 382, mode: os.FileMode(0644), modTime: time.Unix(1595840384, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xc0, 0x2f, 0x1e, 0x64, 0x9, 0x93, 0xe4, 0x8b, 0xf2, 0x98, 0x5a, 0x45, 0xe2, 0x80, 0x88, 0x67, 0x7a, 0x2d, 0xd7, 0x4b, 0xd1, 0x73, 0xb6, 0x6d, 0x15, 0xc2, 0x0, 0x34, 0xcd, 0xa0, 0xdb, 0x20}}
return a, nil
}

View File

@ -20,9 +20,10 @@ import (
// about group membership changes.
// For more information, see https://github.com/status-im/specs/blob/master/status-group-chats-spec.md.
type MembershipUpdateMessage struct {
ChatID string `json:"chatId"` // UUID concatenated with hex-encoded public key of the creator for the chat
Events []MembershipUpdateEvent `json:"events"`
Message *protobuf.ChatMessage `json:"-"`
ChatID string `json:"chatId"` // UUID concatenated with hex-encoded public key of the creator for the chat
Events []MembershipUpdateEvent `json:"events"`
Message *protobuf.ChatMessage `json:"-"`
EmojiReaction *protobuf.EmojiReaction `json:"-"`
}
const signatureLength = 65
@ -59,7 +60,7 @@ func MembershipUpdateEventFromProtobuf(chatID string, raw []byte) (*MembershipUp
}, nil
}
func (m *MembershipUpdateMessage) ToProtobuf() *protobuf.MembershipUpdateMessage {
func (m *MembershipUpdateMessage) ToProtobuf() (*protobuf.MembershipUpdateMessage, error) {
var rawEvents [][]byte
for _, e := range m.Events {
var encodedEvent []byte
@ -67,11 +68,21 @@ func (m *MembershipUpdateMessage) ToProtobuf() *protobuf.MembershipUpdateMessage
encodedEvent = append(encodedEvent, e.RawPayload...)
rawEvents = append(rawEvents, encodedEvent)
}
return &protobuf.MembershipUpdateMessage{
ChatId: m.ChatID,
Events: rawEvents,
Message: m.Message,
mUM := &protobuf.MembershipUpdateMessage{
ChatId: m.ChatID,
Events: rawEvents,
}
// If message is not piggybacking anything, that's a valid case and we just return
switch {
case m.Message != nil:
mUM.ChatEntity = &protobuf.MembershipUpdateMessage_Message{Message: m.Message}
case m.EmojiReaction != nil:
mUM.ChatEntity = &protobuf.MembershipUpdateMessage_EmojiReaction{EmojiReaction: m.EmojiReaction}
}
return mUM, nil
}
func MembershipUpdateMessageFromProtobuf(raw *protobuf.MembershipUpdateMessage) (*MembershipUpdateMessage, error) {
@ -84,15 +95,21 @@ func MembershipUpdateMessageFromProtobuf(raw *protobuf.MembershipUpdateMessage)
events = append(events, *verifiedEvent)
}
return &MembershipUpdateMessage{
ChatID: raw.ChatId,
Events: events,
Message: raw.Message,
ChatID: raw.ChatId,
Events: events,
Message: raw.GetMessage(),
EmojiReaction: raw.GetEmojiReaction(),
}, nil
}
// EncodeMembershipUpdateMessage encodes a MembershipUpdateMessage using protobuf serialization.
func EncodeMembershipUpdateMessage(value MembershipUpdateMessage) ([]byte, error) {
return proto.Marshal(value.ToProtobuf())
pb, err := value.ToProtobuf()
if err != nil {
return nil, err
}
return proto.Marshal(pb)
}
// MembershipUpdateEvent contains an event information.

View File

@ -54,7 +54,8 @@ func TestSignMembershipUpdate(t *testing.T) {
require.NoError(t, err)
// Encode message
encodedMessage := testMembershipUpdateMessageStruct.ToProtobuf()
encodedMessage, err := testMembershipUpdateMessageStruct.ToProtobuf()
require.NoError(t, err)
// Verify it
verifiedMessage, err := MembershipUpdateMessageFromProtobuf(encodedMessage)
require.NoError(t, err)

View File

@ -4,6 +4,7 @@ import (
"crypto/ecdsa"
"encoding/json"
"log"
"reflect"
"github.com/golang/protobuf/proto"
"github.com/jinzhu/copier"
@ -25,7 +26,7 @@ type StatusMessage struct {
// Type is the type of application message contained
Type protobuf.ApplicationMetadataMessage_Type `json:"-"`
// ParsedMessage is the parsed message by the application layer, i.e the output
ParsedMessage interface{} `json:"-"`
ParsedMessage *reflect.Value `json:"-"`
// TransportPayload is the payload as received from the transport layer
TransportPayload []byte `json:"-"`
@ -175,241 +176,90 @@ func (m *StatusMessage) HandleApplicationMetadata() error {
func (m *StatusMessage) HandleApplication() error {
switch m.Type {
case protobuf.ApplicationMetadataMessage_CHAT_MESSAGE:
var message protobuf.ChatMessage
return m.unmarshalProtobufData(new(protobuf.ChatMessage))
err := proto.Unmarshal(m.DecryptedPayload, &message)
if err != nil {
m.ParsedMessage = nil
log.Printf("[message::DecodeMessage] could not decode ChatMessage: %#x, err: %v", m.Hash, err.Error())
} else {
m.ParsedMessage = message
return nil
}
case protobuf.ApplicationMetadataMessage_MEMBERSHIP_UPDATE_MESSAGE:
var message protobuf.MembershipUpdateMessage
err := proto.Unmarshal(m.DecryptedPayload, &message)
if err != nil {
m.ParsedMessage = nil
log.Printf("[message::DecodeMessage] could not decode MembershipUpdateMessage: %#x, err: %v", m.Hash, err.Error())
} else {
m.ParsedMessage = message
return m.unmarshalProtobufData(new(protobuf.MembershipUpdateMessage))
return nil
}
case protobuf.ApplicationMetadataMessage_ACCEPT_REQUEST_ADDRESS_FOR_TRANSACTION:
var message protobuf.AcceptRequestAddressForTransaction
err := proto.Unmarshal(m.DecryptedPayload, &message)
if err != nil {
m.ParsedMessage = nil
log.Printf("[message::DecodeMessage] could not decode AcceptRequestAddressForTransaction: %#x, err: %v", m.Hash, err.Error())
} else {
m.ParsedMessage = message
return m.unmarshalProtobufData(new(protobuf.AcceptRequestAddressForTransaction))
return nil
}
case protobuf.ApplicationMetadataMessage_SEND_TRANSACTION:
var message protobuf.SendTransaction
err := proto.Unmarshal(m.DecryptedPayload, &message)
if err != nil {
m.ParsedMessage = nil
log.Printf("[message::DecodeMessage] could not decode SendTransaction: %#x, err: %v", m.Hash, err.Error())
} else {
m.ParsedMessage = message
return nil
}
return m.unmarshalProtobufData(new(protobuf.SendTransaction))
case protobuf.ApplicationMetadataMessage_REQUEST_TRANSACTION:
var message protobuf.RequestTransaction
err := proto.Unmarshal(m.DecryptedPayload, &message)
if err != nil {
m.ParsedMessage = nil
log.Printf("[message::DecodeMessage] could not decode RequestTransaction: %#x, err: %v", m.Hash, err.Error())
} else {
m.ParsedMessage = message
return nil
}
return m.unmarshalProtobufData(new(protobuf.RequestTransaction))
case protobuf.ApplicationMetadataMessage_DECLINE_REQUEST_ADDRESS_FOR_TRANSACTION:
var message protobuf.DeclineRequestAddressForTransaction
err := proto.Unmarshal(m.DecryptedPayload, &message)
if err != nil {
m.ParsedMessage = nil
log.Printf("[message::DecodeMessage] could not decode DeclineRequestAddressForTransaction: %#x, err: %v", m.Hash, err.Error())
} else {
m.ParsedMessage = message
return m.unmarshalProtobufData(new(protobuf.DeclineRequestAddressForTransaction))
return nil
}
case protobuf.ApplicationMetadataMessage_DECLINE_REQUEST_TRANSACTION:
var message protobuf.DeclineRequestTransaction
err := proto.Unmarshal(m.DecryptedPayload, &message)
if err != nil {
m.ParsedMessage = nil
log.Printf("[message::DecodeMessage] could not decode DeclineRequestTransaction: %#x, err: %v", m.Hash, err.Error())
} else {
m.ParsedMessage = message
return nil
}
return m.unmarshalProtobufData(new(protobuf.DeclineRequestTransaction))
case protobuf.ApplicationMetadataMessage_REQUEST_ADDRESS_FOR_TRANSACTION:
var message protobuf.RequestAddressForTransaction
err := proto.Unmarshal(m.DecryptedPayload, &message)
if err != nil {
m.ParsedMessage = nil
log.Printf("[message::DecodeMessage] could not decode RequestAddressForTransaction: %#x, err: %v", m.Hash, err.Error())
} else {
m.ParsedMessage = message
return nil
}
return m.unmarshalProtobufData(new(protobuf.RequestAddressForTransaction))
case protobuf.ApplicationMetadataMessage_CONTACT_UPDATE:
var message protobuf.ContactUpdate
err := proto.Unmarshal(m.DecryptedPayload, &message)
if err != nil {
m.ParsedMessage = nil
log.Printf("[message::DecodeMessage] could not decode ContactUpdate: %#x, err: %v", m.Hash, err.Error())
} else {
m.ParsedMessage = message
return m.unmarshalProtobufData(new(protobuf.ContactUpdate))
return nil
}
case protobuf.ApplicationMetadataMessage_SYNC_INSTALLATION:
var message protobuf.SyncInstallation
err := proto.Unmarshal(m.DecryptedPayload, &message)
if err != nil {
m.ParsedMessage = nil
log.Printf("[message::DecodeMessage] could not decode SyncInstallation: %#x, err: %v", m.Hash, err.Error())
} else {
m.ParsedMessage = message
return m.unmarshalProtobufData(new(protobuf.SyncInstallation))
return nil
}
case protobuf.ApplicationMetadataMessage_SYNC_INSTALLATION_CONTACT:
var message protobuf.SyncInstallationContact
log.Printf("Sync installation contact")
err := proto.Unmarshal(m.DecryptedPayload, &message)
if err != nil {
m.ParsedMessage = nil
log.Printf("[message::DecodeMessage] could not decode SyncInstallationContact: %#x, err: %v", m.Hash, err.Error())
} else {
m.ParsedMessage = message
return m.unmarshalProtobufData(new(protobuf.SyncInstallationContact))
return nil
}
case protobuf.ApplicationMetadataMessage_SYNC_INSTALLATION_PUBLIC_CHAT:
var message protobuf.SyncInstallationPublicChat
err := proto.Unmarshal(m.DecryptedPayload, &message)
if err != nil {
m.ParsedMessage = nil
log.Printf("[message::DecodeMessage] could not decode SyncInstallationPublicChat: %#x, err: %v", m.Hash, err.Error())
} else {
m.ParsedMessage = message
return m.unmarshalProtobufData(new(protobuf.SyncInstallationPublicChat))
return nil
}
case protobuf.ApplicationMetadataMessage_SYNC_INSTALLATION_ACCOUNT:
var message protobuf.SyncInstallationAccount
err := proto.Unmarshal(m.DecryptedPayload, &message)
if err != nil {
m.ParsedMessage = nil
log.Printf("[message::DecodeMessage] could not decode SyncInstallationAccount: %#x, err: %v", m.Hash, err.Error())
} else {
m.ParsedMessage = message
return m.unmarshalProtobufData(new(protobuf.SyncInstallationAccount))
return nil
}
case protobuf.ApplicationMetadataMessage_PAIR_INSTALLATION:
var message protobuf.PairInstallation
err := proto.Unmarshal(m.DecryptedPayload, &message)
if err != nil {
m.ParsedMessage = nil
log.Printf("[message::DecodeMessage] could not decode PairInstallation: %#x, err: %v", m.Hash, err.Error())
} else {
m.ParsedMessage = message
return nil
}
case protobuf.ApplicationMetadataMessage_PUSH_NOTIFICATION_REGISTRATION:
// This message is a bit different as it's encrypted, so we pass it straight through
m.ParsedMessage = m.DecryptedPayload
return nil
return m.unmarshalProtobufData(new(protobuf.PairInstallation))
case protobuf.ApplicationMetadataMessage_CONTACT_CODE_ADVERTISEMENT:
var message protobuf.ContactCodeAdvertisement
err := proto.Unmarshal(m.DecryptedPayload, &message)
if err != nil {
m.ParsedMessage = nil
log.Printf("[message::DecodeMessage] could not decode ContactCodeAdvertisement: %#x, err: %v", m.Hash, err.Error())
} else {
m.ParsedMessage = message
return nil
}
return m.unmarshalProtobufData(new(protobuf.ContactCodeAdvertisement))
case protobuf.ApplicationMetadataMessage_PUSH_NOTIFICATION_REQUEST:
var message protobuf.PushNotificationRequest
err := proto.Unmarshal(m.DecryptedPayload, &message)
if err != nil {
m.ParsedMessage = nil
log.Printf("[message::DecodeMessage] could not decode PushNotificationRequest: %#x, err: %v", m.Hash, err.Error())
} else {
m.ParsedMessage = message
return nil
}
return m.unmarshalProtobufData(new(protobuf.PushNotificationRequest))
case protobuf.ApplicationMetadataMessage_PUSH_NOTIFICATION_REGISTRATION_RESPONSE:
var message protobuf.PushNotificationRegistrationResponse
err := proto.Unmarshal(m.DecryptedPayload, &message)
if err != nil {
m.ParsedMessage = nil
log.Printf("[message::DecodeMessage] could not decode PushNotificationRegistrationResponse: %#x, err: %v", m.Hash, err.Error())
} else {
m.ParsedMessage = message
return nil
}
return m.unmarshalProtobufData(new(protobuf.PushNotificationRegistrationResponse))
case protobuf.ApplicationMetadataMessage_PUSH_NOTIFICATION_QUERY:
var message protobuf.PushNotificationQuery
err := proto.Unmarshal(m.DecryptedPayload, &message)
if err != nil {
m.ParsedMessage = nil
log.Printf("[message::DecodeMessage] could not decode PushNotificationQuery: %#x, err: %v", m.Hash, err.Error())
} else {
m.ParsedMessage = message
return nil
}
return m.unmarshalProtobufData(new(protobuf.PushNotificationQuery))
case protobuf.ApplicationMetadataMessage_PUSH_NOTIFICATION_QUERY_RESPONSE:
var message protobuf.PushNotificationQueryResponse
err := proto.Unmarshal(m.DecryptedPayload, &message)
if err != nil {
m.ParsedMessage = nil
log.Printf("[message::DecodeMessage] could not decode PushNotificationQueryResponse: %#x, err: %v", m.Hash, err.Error())
} else {
m.ParsedMessage = message
return nil
}
return m.unmarshalProtobufData(new(protobuf.PushNotificationQueryResponse))
case protobuf.ApplicationMetadataMessage_PUSH_NOTIFICATION_RESPONSE:
var message protobuf.PushNotificationResponse
err := proto.Unmarshal(m.DecryptedPayload, &message)
if err != nil {
m.ParsedMessage = nil
log.Printf("[message::DecodeMessage] could not decode PushNotificationResponse: %#x, err: %v", m.Hash, err.Error())
} else {
m.ParsedMessage = message
return nil
}
return m.unmarshalProtobufData(new(protobuf.PushNotificationResponse))
case protobuf.ApplicationMetadataMessage_EMOJI_REACTION:
return m.unmarshalProtobufData(new(protobuf.EmojiReaction))
case protobuf.ApplicationMetadataMessage_PUSH_NOTIFICATION_REGISTRATION:
// This message is a bit different as it's encrypted, so we pass it straight through
v := reflect.ValueOf(m.DecryptedPayload)
m.ParsedMessage = &v
return nil
}
return nil
}
func (m *StatusMessage) unmarshalProtobufData(pb proto.Message) error {
var ptr proto.Message
rv := reflect.ValueOf(pb)
if rv.Kind() == reflect.Ptr {
ptr = pb
} else {
ptr = rv.Addr().Interface().(proto.Message)
}
err := proto.Unmarshal(m.DecryptedPayload, ptr)
if err != nil {
m.ParsedMessage = nil
log.Printf("[message::DecodeMessage] could not decode %T: %#x, err: %v", pb, m.Hash, err.Error())
} else {
rv = reflect.ValueOf(ptr)
elem := rv.Elem()
m.ParsedMessage = &elem
return nil
}
return nil
}

View File

@ -17,6 +17,7 @@ import (
"github.com/status-im/status-go/mailserver"
"github.com/status-im/status-go/protocol"
"github.com/status-im/status-go/protocol/encryption/multidevice"
"github.com/status-im/status-go/protocol/protobuf"
"github.com/status-im/status-go/protocol/pushnotificationclient"
"github.com/status-im/status-go/protocol/transport"
"github.com/status-im/status-go/services/ext/mailservers"
@ -511,6 +512,20 @@ func (api *PublicAPI) RegisteredForPushNotifications() (bool, error) {
return api.service.messenger.RegisteredForPushNotifications()
}
// Emoji
func (api *PublicAPI) SendEmojiReaction(ctx context.Context, chatID, messageID string, emojiID protobuf.EmojiReaction_Type) (*protocol.MessengerResponse, error) {
return api.service.messenger.SendEmojiReaction(ctx, chatID, messageID, emojiID)
}
func (api *PublicAPI) SendEmojiReactionRetraction(ctx context.Context, emojiReactionID string) (*protocol.MessengerResponse, error) {
return api.service.messenger.SendEmojiReactionRetraction(ctx, emojiReactionID)
}
func (api *PublicAPI) EmojiReactionsByChatID(chatID string, cursor string, limit int) ([]*protocol.EmojiReaction, error) {
return api.service.messenger.EmojiReactionsByChatID(chatID, cursor, limit)
}
// Echo is a method for testing purposes.
func (api *PublicAPI) Echo(ctx context.Context, message string) (string, error) {
return message, nil

View File

@ -9,7 +9,7 @@ import (
_ "github.com/mattn/go-isatty"
)
// NewColorable return new instance of Writer which handle escape sequence.
// NewColorable returns new instance of Writer which handles escape sequence.
func NewColorable(file *os.File) io.Writer {
if file == nil {
panic("nil passed instead of *os.File to NewColorable()")
@ -18,12 +18,12 @@ func NewColorable(file *os.File) io.Writer {
return file
}
// NewColorableStdout return new instance of Writer which handle escape sequence for stdout.
// NewColorableStdout returns new instance of Writer which handles escape sequence for stdout.
func NewColorableStdout() io.Writer {
return os.Stdout
}
// NewColorableStderr return new instance of Writer which handle escape sequence for stderr.
// NewColorableStderr returns new instance of Writer which handles escape sequence for stderr.
func NewColorableStderr() io.Writer {
return os.Stderr
}

View File

@ -10,7 +10,7 @@ import (
_ "github.com/mattn/go-isatty"
)
// NewColorable return new instance of Writer which handle escape sequence.
// NewColorable returns new instance of Writer which handles escape sequence.
func NewColorable(file *os.File) io.Writer {
if file == nil {
panic("nil passed instead of *os.File to NewColorable()")
@ -19,12 +19,12 @@ func NewColorable(file *os.File) io.Writer {
return file
}
// NewColorableStdout return new instance of Writer which handle escape sequence for stdout.
// NewColorableStdout returns new instance of Writer which handles escape sequence for stdout.
func NewColorableStdout() io.Writer {
return os.Stdout
}
// NewColorableStderr return new instance of Writer which handle escape sequence for stderr.
// NewColorableStderr returns new instance of Writer which handles escape sequence for stderr.
func NewColorableStderr() io.Writer {
return os.Stderr
}

View File

@ -81,7 +81,7 @@ var (
procCreateConsoleScreenBuffer = kernel32.NewProc("CreateConsoleScreenBuffer")
)
// Writer provide colorable Writer to the console
// Writer provides colorable Writer to the console
type Writer struct {
out io.Writer
handle syscall.Handle
@ -91,7 +91,7 @@ type Writer struct {
rest bytes.Buffer
}
// NewColorable return new instance of Writer which handle escape sequence from File.
// NewColorable returns new instance of Writer which handles escape sequence from File.
func NewColorable(file *os.File) io.Writer {
if file == nil {
panic("nil passed instead of *os.File to NewColorable()")
@ -106,12 +106,12 @@ func NewColorable(file *os.File) io.Writer {
return file
}
// NewColorableStdout return new instance of Writer which handle escape sequence for stdout.
// NewColorableStdout returns new instance of Writer which handles escape sequence for stdout.
func NewColorableStdout() io.Writer {
return NewColorable(os.Stdout)
}
// NewColorableStderr return new instance of Writer which handle escape sequence for stderr.
// NewColorableStderr returns new instance of Writer which handles escape sequence for stderr.
func NewColorableStderr() io.Writer {
return NewColorable(os.Stderr)
}
@ -414,7 +414,15 @@ func doTitleSequence(er *bytes.Reader) error {
return nil
}
// Write write data on console
// returns Atoi(s) unless s == "" in which case it returns def
func atoiWithDefault(s string, def int) (int, error) {
if s == "" {
return def, nil
}
return strconv.Atoi(s)
}
// Write writes data on console
func (w *Writer) Write(data []byte) (n int, err error) {
var csbi consoleScreenBufferInfo
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
@ -500,7 +508,7 @@ loop:
switch m {
case 'A':
n, err = strconv.Atoi(buf.String())
n, err = atoiWithDefault(buf.String(), 1)
if err != nil {
continue
}
@ -508,7 +516,7 @@ loop:
csbi.cursorPosition.y -= short(n)
procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
case 'B':
n, err = strconv.Atoi(buf.String())
n, err = atoiWithDefault(buf.String(), 1)
if err != nil {
continue
}
@ -516,7 +524,7 @@ loop:
csbi.cursorPosition.y += short(n)
procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
case 'C':
n, err = strconv.Atoi(buf.String())
n, err = atoiWithDefault(buf.String(), 1)
if err != nil {
continue
}
@ -524,7 +532,7 @@ loop:
csbi.cursorPosition.x += short(n)
procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
case 'D':
n, err = strconv.Atoi(buf.String())
n, err = atoiWithDefault(buf.String(), 1)
if err != nil {
continue
}
@ -557,6 +565,9 @@ loop:
if err != nil {
continue
}
if n < 1 {
n = 1
}
procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
csbi.cursorPosition.x = short(n - 1)
procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
@ -635,6 +646,20 @@ loop:
}
procFillConsoleOutputCharacter.Call(uintptr(handle), uintptr(' '), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written)))
procFillConsoleOutputAttribute.Call(uintptr(handle), uintptr(csbi.attributes), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written)))
case 'X':
n := 0
if buf.Len() > 0 {
n, err = strconv.Atoi(buf.String())
if err != nil {
continue
}
}
procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
var cursor coord
var written dword
cursor = coord{x: csbi.cursorPosition.x, y: csbi.cursorPosition.y}
procFillConsoleOutputCharacter.Call(uintptr(handle), uintptr(' '), uintptr(n), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written)))
procFillConsoleOutputAttribute.Call(uintptr(handle), uintptr(csbi.attributes), uintptr(n), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written)))
case 'm':
procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
attr := csbi.attributes

View File

@ -1,3 +1,3 @@
module github.com/mattn/go-colorable
require github.com/mattn/go-isatty v0.0.5
require github.com/mattn/go-isatty v0.0.8

View File

@ -5,17 +5,17 @@ import (
"io"
)
// NonColorable hold writer but remove escape sequence.
// NonColorable holds writer but removes escape sequence.
type NonColorable struct {
out io.Writer
}
// NewNonColorable return new instance of Writer which remove escape sequence from Writer.
// NewNonColorable returns new instance of Writer which removes escape sequence from Writer.
func NewNonColorable(w io.Writer) io.Writer {
return &NonColorable{out: w}
}
// Write write data on console
// Write writes data on console
func (w *NonColorable) Write(data []byte) (n int, err error) {
er := bytes.NewReader(data)
var bw [1]byte

View File

@ -1,3 +1,5 @@
module github.com/mattn/go-isatty
require golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223
require golang.org/x/sys v0.0.0-20191008105621-543471e840be
go 1.14

View File

@ -1,2 +1,4 @@
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223 h1:DH4skfRX4EBpamg7iV4ZlCpblAHI6s6TDM39bFZumv8=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a h1:aYOabOQFp6Vj6W1F80affTUvO9UxmJRx8K0gsfABByQ=
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191008105621-543471e840be h1:QAcqgptGM8IQBC9K/RC4o+O9YmqEm0diQn9QmZw/0mU=
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=

View File

@ -1,4 +1,4 @@
// +build appengine js
// +build appengine js nacl
package isatty

22
vendor/github.com/mattn/go-isatty/isatty_plan9.go generated vendored Normal file
View File

@ -0,0 +1,22 @@
// +build plan9
package isatty
import (
"syscall"
)
// IsTerminal returns true if the given file descriptor is a terminal.
func IsTerminal(fd uintptr) bool {
path, err := syscall.Fd2path(fd)
if err != nil {
return false
}
return path == "/dev/cons" || path == "/mnt/term/dev/cons"
}
// IsCygwinTerminal return true if the file descriptor is a cygwin or msys2
// terminal. This is also always false on this environment.
func IsCygwinTerminal(fd uintptr) bool {
return false
}

View File

@ -1,4 +1,4 @@
// +build linux
// +build linux aix
// +build !appengine
// +build !android

View File

@ -4,6 +4,7 @@
package isatty
import (
"errors"
"strings"
"syscall"
"unicode/utf16"
@ -11,15 +12,18 @@ import (
)
const (
fileNameInfo uintptr = 2
fileTypePipe = 3
objectNameInfo uintptr = 1
fileNameInfo = 2
fileTypePipe = 3
)
var (
kernel32 = syscall.NewLazyDLL("kernel32.dll")
ntdll = syscall.NewLazyDLL("ntdll.dll")
procGetConsoleMode = kernel32.NewProc("GetConsoleMode")
procGetFileInformationByHandleEx = kernel32.NewProc("GetFileInformationByHandleEx")
procGetFileType = kernel32.NewProc("GetFileType")
procNtQueryObject = ntdll.NewProc("NtQueryObject")
)
func init() {
@ -45,7 +49,10 @@ func isCygwinPipeName(name string) bool {
return false
}
if token[0] != `\msys` && token[0] != `\cygwin` {
if token[0] != `\msys` &&
token[0] != `\cygwin` &&
token[0] != `\Device\NamedPipe\msys` &&
token[0] != `\Device\NamedPipe\cygwin` {
return false
}
@ -68,11 +75,35 @@ func isCygwinPipeName(name string) bool {
return true
}
// getFileNameByHandle use the undocomented ntdll NtQueryObject to get file full name from file handler
// since GetFileInformationByHandleEx is not avilable under windows Vista and still some old fashion
// guys are using Windows XP, this is a workaround for those guys, it will also work on system from
// Windows vista to 10
// see https://stackoverflow.com/a/18792477 for details
func getFileNameByHandle(fd uintptr) (string, error) {
if procNtQueryObject == nil {
return "", errors.New("ntdll.dll: NtQueryObject not supported")
}
var buf [4 + syscall.MAX_PATH]uint16
var result int
r, _, e := syscall.Syscall6(procNtQueryObject.Addr(), 5,
fd, objectNameInfo, uintptr(unsafe.Pointer(&buf)), uintptr(2*len(buf)), uintptr(unsafe.Pointer(&result)), 0)
if r != 0 {
return "", e
}
return string(utf16.Decode(buf[4 : 4+buf[0]/2])), nil
}
// IsCygwinTerminal() return true if the file descriptor is a cygwin or msys2
// terminal.
func IsCygwinTerminal(fd uintptr) bool {
if procGetFileInformationByHandleEx == nil {
return false
name, err := getFileNameByHandle(fd)
if err != nil {
return false
}
return isCygwinPipeName(name)
}
// Cygwin/msys's pty is a pipe.

3
vendor/github.com/mattn/go-runewidth/go.mod generated vendored Normal file
View File

@ -0,0 +1,3 @@
module github.com/mattn/go-runewidth
go 1.9

View File

@ -4,6 +4,8 @@ import (
"os"
)
//go:generate go run script/generate.go
var (
// EastAsianWidth will be set true if the current locale is CJK
EastAsianWidth bool
@ -82,728 +84,6 @@ var nonprint = table{
{0xFEFF, 0xFEFF}, {0xFFF9, 0xFFFB}, {0xFFFE, 0xFFFF},
}
var combining = table{
{0x0300, 0x036F}, {0x0483, 0x0489}, {0x0591, 0x05BD},
{0x05BF, 0x05BF}, {0x05C1, 0x05C2}, {0x05C4, 0x05C5},
{0x05C7, 0x05C7}, {0x0610, 0x061A}, {0x064B, 0x065F},
{0x0670, 0x0670}, {0x06D6, 0x06DC}, {0x06DF, 0x06E4},
{0x06E7, 0x06E8}, {0x06EA, 0x06ED}, {0x0711, 0x0711},
{0x0730, 0x074A}, {0x07A6, 0x07B0}, {0x07EB, 0x07F3},
{0x0816, 0x0819}, {0x081B, 0x0823}, {0x0825, 0x0827},
{0x0829, 0x082D}, {0x0859, 0x085B}, {0x08D4, 0x08E1},
{0x08E3, 0x0903}, {0x093A, 0x093C}, {0x093E, 0x094F},
{0x0951, 0x0957}, {0x0962, 0x0963}, {0x0981, 0x0983},
{0x09BC, 0x09BC}, {0x09BE, 0x09C4}, {0x09C7, 0x09C8},
{0x09CB, 0x09CD}, {0x09D7, 0x09D7}, {0x09E2, 0x09E3},
{0x0A01, 0x0A03}, {0x0A3C, 0x0A3C}, {0x0A3E, 0x0A42},
{0x0A47, 0x0A48}, {0x0A4B, 0x0A4D}, {0x0A51, 0x0A51},
{0x0A70, 0x0A71}, {0x0A75, 0x0A75}, {0x0A81, 0x0A83},
{0x0ABC, 0x0ABC}, {0x0ABE, 0x0AC5}, {0x0AC7, 0x0AC9},
{0x0ACB, 0x0ACD}, {0x0AE2, 0x0AE3}, {0x0B01, 0x0B03},
{0x0B3C, 0x0B3C}, {0x0B3E, 0x0B44}, {0x0B47, 0x0B48},
{0x0B4B, 0x0B4D}, {0x0B56, 0x0B57}, {0x0B62, 0x0B63},
{0x0B82, 0x0B82}, {0x0BBE, 0x0BC2}, {0x0BC6, 0x0BC8},
{0x0BCA, 0x0BCD}, {0x0BD7, 0x0BD7}, {0x0C00, 0x0C03},
{0x0C3E, 0x0C44}, {0x0C46, 0x0C48}, {0x0C4A, 0x0C4D},
{0x0C55, 0x0C56}, {0x0C62, 0x0C63}, {0x0C81, 0x0C83},
{0x0CBC, 0x0CBC}, {0x0CBE, 0x0CC4}, {0x0CC6, 0x0CC8},
{0x0CCA, 0x0CCD}, {0x0CD5, 0x0CD6}, {0x0CE2, 0x0CE3},
{0x0D01, 0x0D03}, {0x0D3E, 0x0D44}, {0x0D46, 0x0D48},
{0x0D4A, 0x0D4D}, {0x0D57, 0x0D57}, {0x0D62, 0x0D63},
{0x0D82, 0x0D83}, {0x0DCA, 0x0DCA}, {0x0DCF, 0x0DD4},
{0x0DD6, 0x0DD6}, {0x0DD8, 0x0DDF}, {0x0DF2, 0x0DF3},
{0x0E31, 0x0E31}, {0x0E34, 0x0E3A}, {0x0E47, 0x0E4E},
{0x0EB1, 0x0EB1}, {0x0EB4, 0x0EB9}, {0x0EBB, 0x0EBC},
{0x0EC8, 0x0ECD}, {0x0F18, 0x0F19}, {0x0F35, 0x0F35},
{0x0F37, 0x0F37}, {0x0F39, 0x0F39}, {0x0F3E, 0x0F3F},
{0x0F71, 0x0F84}, {0x0F86, 0x0F87}, {0x0F8D, 0x0F97},
{0x0F99, 0x0FBC}, {0x0FC6, 0x0FC6}, {0x102B, 0x103E},
{0x1056, 0x1059}, {0x105E, 0x1060}, {0x1062, 0x1064},
{0x1067, 0x106D}, {0x1071, 0x1074}, {0x1082, 0x108D},
{0x108F, 0x108F}, {0x109A, 0x109D}, {0x135D, 0x135F},
{0x1712, 0x1714}, {0x1732, 0x1734}, {0x1752, 0x1753},
{0x1772, 0x1773}, {0x17B4, 0x17D3}, {0x17DD, 0x17DD},
{0x180B, 0x180D}, {0x1885, 0x1886}, {0x18A9, 0x18A9},
{0x1920, 0x192B}, {0x1930, 0x193B}, {0x1A17, 0x1A1B},
{0x1A55, 0x1A5E}, {0x1A60, 0x1A7C}, {0x1A7F, 0x1A7F},
{0x1AB0, 0x1ABE}, {0x1B00, 0x1B04}, {0x1B34, 0x1B44},
{0x1B6B, 0x1B73}, {0x1B80, 0x1B82}, {0x1BA1, 0x1BAD},
{0x1BE6, 0x1BF3}, {0x1C24, 0x1C37}, {0x1CD0, 0x1CD2},
{0x1CD4, 0x1CE8}, {0x1CED, 0x1CED}, {0x1CF2, 0x1CF4},
{0x1CF8, 0x1CF9}, {0x1DC0, 0x1DF5}, {0x1DFB, 0x1DFF},
{0x20D0, 0x20F0}, {0x2CEF, 0x2CF1}, {0x2D7F, 0x2D7F},
{0x2DE0, 0x2DFF}, {0x302A, 0x302F}, {0x3099, 0x309A},
{0xA66F, 0xA672}, {0xA674, 0xA67D}, {0xA69E, 0xA69F},
{0xA6F0, 0xA6F1}, {0xA802, 0xA802}, {0xA806, 0xA806},
{0xA80B, 0xA80B}, {0xA823, 0xA827}, {0xA880, 0xA881},
{0xA8B4, 0xA8C5}, {0xA8E0, 0xA8F1}, {0xA926, 0xA92D},
{0xA947, 0xA953}, {0xA980, 0xA983}, {0xA9B3, 0xA9C0},
{0xA9E5, 0xA9E5}, {0xAA29, 0xAA36}, {0xAA43, 0xAA43},
{0xAA4C, 0xAA4D}, {0xAA7B, 0xAA7D}, {0xAAB0, 0xAAB0},
{0xAAB2, 0xAAB4}, {0xAAB7, 0xAAB8}, {0xAABE, 0xAABF},
{0xAAC1, 0xAAC1}, {0xAAEB, 0xAAEF}, {0xAAF5, 0xAAF6},
{0xABE3, 0xABEA}, {0xABEC, 0xABED}, {0xFB1E, 0xFB1E},
{0xFE00, 0xFE0F}, {0xFE20, 0xFE2F}, {0x101FD, 0x101FD},
{0x102E0, 0x102E0}, {0x10376, 0x1037A}, {0x10A01, 0x10A03},
{0x10A05, 0x10A06}, {0x10A0C, 0x10A0F}, {0x10A38, 0x10A3A},
{0x10A3F, 0x10A3F}, {0x10AE5, 0x10AE6}, {0x11000, 0x11002},
{0x11038, 0x11046}, {0x1107F, 0x11082}, {0x110B0, 0x110BA},
{0x11100, 0x11102}, {0x11127, 0x11134}, {0x11173, 0x11173},
{0x11180, 0x11182}, {0x111B3, 0x111C0}, {0x111CA, 0x111CC},
{0x1122C, 0x11237}, {0x1123E, 0x1123E}, {0x112DF, 0x112EA},
{0x11300, 0x11303}, {0x1133C, 0x1133C}, {0x1133E, 0x11344},
{0x11347, 0x11348}, {0x1134B, 0x1134D}, {0x11357, 0x11357},
{0x11362, 0x11363}, {0x11366, 0x1136C}, {0x11370, 0x11374},
{0x11435, 0x11446}, {0x114B0, 0x114C3}, {0x115AF, 0x115B5},
{0x115B8, 0x115C0}, {0x115DC, 0x115DD}, {0x11630, 0x11640},
{0x116AB, 0x116B7}, {0x1171D, 0x1172B}, {0x11C2F, 0x11C36},
{0x11C38, 0x11C3F}, {0x11C92, 0x11CA7}, {0x11CA9, 0x11CB6},
{0x16AF0, 0x16AF4}, {0x16B30, 0x16B36}, {0x16F51, 0x16F7E},
{0x16F8F, 0x16F92}, {0x1BC9D, 0x1BC9E}, {0x1D165, 0x1D169},
{0x1D16D, 0x1D172}, {0x1D17B, 0x1D182}, {0x1D185, 0x1D18B},
{0x1D1AA, 0x1D1AD}, {0x1D242, 0x1D244}, {0x1DA00, 0x1DA36},
{0x1DA3B, 0x1DA6C}, {0x1DA75, 0x1DA75}, {0x1DA84, 0x1DA84},
{0x1DA9B, 0x1DA9F}, {0x1DAA1, 0x1DAAF}, {0x1E000, 0x1E006},
{0x1E008, 0x1E018}, {0x1E01B, 0x1E021}, {0x1E023, 0x1E024},
{0x1E026, 0x1E02A}, {0x1E8D0, 0x1E8D6}, {0x1E944, 0x1E94A},
{0xE0100, 0xE01EF},
}
var doublewidth = table{
{0x1100, 0x115F}, {0x231A, 0x231B}, {0x2329, 0x232A},
{0x23E9, 0x23EC}, {0x23F0, 0x23F0}, {0x23F3, 0x23F3},
{0x25FD, 0x25FE}, {0x2614, 0x2615}, {0x2648, 0x2653},
{0x267F, 0x267F}, {0x2693, 0x2693}, {0x26A1, 0x26A1},
{0x26AA, 0x26AB}, {0x26BD, 0x26BE}, {0x26C4, 0x26C5},
{0x26CE, 0x26CE}, {0x26D4, 0x26D4}, {0x26EA, 0x26EA},
{0x26F2, 0x26F3}, {0x26F5, 0x26F5}, {0x26FA, 0x26FA},
{0x26FD, 0x26FD}, {0x2705, 0x2705}, {0x270A, 0x270B},
{0x2728, 0x2728}, {0x274C, 0x274C}, {0x274E, 0x274E},
{0x2753, 0x2755}, {0x2757, 0x2757}, {0x2795, 0x2797},
{0x27B0, 0x27B0}, {0x27BF, 0x27BF}, {0x2B1B, 0x2B1C},
{0x2B50, 0x2B50}, {0x2B55, 0x2B55}, {0x2E80, 0x2E99},
{0x2E9B, 0x2EF3}, {0x2F00, 0x2FD5}, {0x2FF0, 0x2FFB},
{0x3000, 0x303E}, {0x3041, 0x3096}, {0x3099, 0x30FF},
{0x3105, 0x312D}, {0x3131, 0x318E}, {0x3190, 0x31BA},
{0x31C0, 0x31E3}, {0x31F0, 0x321E}, {0x3220, 0x3247},
{0x3250, 0x32FE}, {0x3300, 0x4DBF}, {0x4E00, 0xA48C},
{0xA490, 0xA4C6}, {0xA960, 0xA97C}, {0xAC00, 0xD7A3},
{0xF900, 0xFAFF}, {0xFE10, 0xFE19}, {0xFE30, 0xFE52},
{0xFE54, 0xFE66}, {0xFE68, 0xFE6B}, {0xFF01, 0xFF60},
{0xFFE0, 0xFFE6}, {0x16FE0, 0x16FE0}, {0x17000, 0x187EC},
{0x18800, 0x18AF2}, {0x1B000, 0x1B001}, {0x1F004, 0x1F004},
{0x1F0CF, 0x1F0CF}, {0x1F18E, 0x1F18E}, {0x1F191, 0x1F19A},
{0x1F200, 0x1F202}, {0x1F210, 0x1F23B}, {0x1F240, 0x1F248},
{0x1F250, 0x1F251}, {0x1F300, 0x1F320}, {0x1F32D, 0x1F335},
{0x1F337, 0x1F37C}, {0x1F37E, 0x1F393}, {0x1F3A0, 0x1F3CA},
{0x1F3CF, 0x1F3D3}, {0x1F3E0, 0x1F3F0}, {0x1F3F4, 0x1F3F4},
{0x1F3F8, 0x1F43E}, {0x1F440, 0x1F440}, {0x1F442, 0x1F4FC},
{0x1F4FF, 0x1F53D}, {0x1F54B, 0x1F54E}, {0x1F550, 0x1F567},
{0x1F57A, 0x1F57A}, {0x1F595, 0x1F596}, {0x1F5A4, 0x1F5A4},
{0x1F5FB, 0x1F64F}, {0x1F680, 0x1F6C5}, {0x1F6CC, 0x1F6CC},
{0x1F6D0, 0x1F6D2}, {0x1F6EB, 0x1F6EC}, {0x1F6F4, 0x1F6F6},
{0x1F910, 0x1F91E}, {0x1F920, 0x1F927}, {0x1F930, 0x1F930},
{0x1F933, 0x1F93E}, {0x1F940, 0x1F94B}, {0x1F950, 0x1F95E},
{0x1F980, 0x1F991}, {0x1F9C0, 0x1F9C0}, {0x20000, 0x2FFFD},
{0x30000, 0x3FFFD},
}
var ambiguous = table{
{0x00A1, 0x00A1}, {0x00A4, 0x00A4}, {0x00A7, 0x00A8},
{0x00AA, 0x00AA}, {0x00AD, 0x00AE}, {0x00B0, 0x00B4},
{0x00B6, 0x00BA}, {0x00BC, 0x00BF}, {0x00C6, 0x00C6},
{0x00D0, 0x00D0}, {0x00D7, 0x00D8}, {0x00DE, 0x00E1},
{0x00E6, 0x00E6}, {0x00E8, 0x00EA}, {0x00EC, 0x00ED},
{0x00F0, 0x00F0}, {0x00F2, 0x00F3}, {0x00F7, 0x00FA},
{0x00FC, 0x00FC}, {0x00FE, 0x00FE}, {0x0101, 0x0101},
{0x0111, 0x0111}, {0x0113, 0x0113}, {0x011B, 0x011B},
{0x0126, 0x0127}, {0x012B, 0x012B}, {0x0131, 0x0133},
{0x0138, 0x0138}, {0x013F, 0x0142}, {0x0144, 0x0144},
{0x0148, 0x014B}, {0x014D, 0x014D}, {0x0152, 0x0153},
{0x0166, 0x0167}, {0x016B, 0x016B}, {0x01CE, 0x01CE},
{0x01D0, 0x01D0}, {0x01D2, 0x01D2}, {0x01D4, 0x01D4},
{0x01D6, 0x01D6}, {0x01D8, 0x01D8}, {0x01DA, 0x01DA},
{0x01DC, 0x01DC}, {0x0251, 0x0251}, {0x0261, 0x0261},
{0x02C4, 0x02C4}, {0x02C7, 0x02C7}, {0x02C9, 0x02CB},
{0x02CD, 0x02CD}, {0x02D0, 0x02D0}, {0x02D8, 0x02DB},
{0x02DD, 0x02DD}, {0x02DF, 0x02DF}, {0x0300, 0x036F},
{0x0391, 0x03A1}, {0x03A3, 0x03A9}, {0x03B1, 0x03C1},
{0x03C3, 0x03C9}, {0x0401, 0x0401}, {0x0410, 0x044F},
{0x0451, 0x0451}, {0x2010, 0x2010}, {0x2013, 0x2016},
{0x2018, 0x2019}, {0x201C, 0x201D}, {0x2020, 0x2022},
{0x2024, 0x2027}, {0x2030, 0x2030}, {0x2032, 0x2033},
{0x2035, 0x2035}, {0x203B, 0x203B}, {0x203E, 0x203E},
{0x2074, 0x2074}, {0x207F, 0x207F}, {0x2081, 0x2084},
{0x20AC, 0x20AC}, {0x2103, 0x2103}, {0x2105, 0x2105},
{0x2109, 0x2109}, {0x2113, 0x2113}, {0x2116, 0x2116},
{0x2121, 0x2122}, {0x2126, 0x2126}, {0x212B, 0x212B},
{0x2153, 0x2154}, {0x215B, 0x215E}, {0x2160, 0x216B},
{0x2170, 0x2179}, {0x2189, 0x2189}, {0x2190, 0x2199},
{0x21B8, 0x21B9}, {0x21D2, 0x21D2}, {0x21D4, 0x21D4},
{0x21E7, 0x21E7}, {0x2200, 0x2200}, {0x2202, 0x2203},
{0x2207, 0x2208}, {0x220B, 0x220B}, {0x220F, 0x220F},
{0x2211, 0x2211}, {0x2215, 0x2215}, {0x221A, 0x221A},
{0x221D, 0x2220}, {0x2223, 0x2223}, {0x2225, 0x2225},
{0x2227, 0x222C}, {0x222E, 0x222E}, {0x2234, 0x2237},
{0x223C, 0x223D}, {0x2248, 0x2248}, {0x224C, 0x224C},
{0x2252, 0x2252}, {0x2260, 0x2261}, {0x2264, 0x2267},
{0x226A, 0x226B}, {0x226E, 0x226F}, {0x2282, 0x2283},
{0x2286, 0x2287}, {0x2295, 0x2295}, {0x2299, 0x2299},
{0x22A5, 0x22A5}, {0x22BF, 0x22BF}, {0x2312, 0x2312},
{0x2460, 0x24E9}, {0x24EB, 0x254B}, {0x2550, 0x2573},
{0x2580, 0x258F}, {0x2592, 0x2595}, {0x25A0, 0x25A1},
{0x25A3, 0x25A9}, {0x25B2, 0x25B3}, {0x25B6, 0x25B7},
{0x25BC, 0x25BD}, {0x25C0, 0x25C1}, {0x25C6, 0x25C8},
{0x25CB, 0x25CB}, {0x25CE, 0x25D1}, {0x25E2, 0x25E5},
{0x25EF, 0x25EF}, {0x2605, 0x2606}, {0x2609, 0x2609},
{0x260E, 0x260F}, {0x261C, 0x261C}, {0x261E, 0x261E},
{0x2640, 0x2640}, {0x2642, 0x2642}, {0x2660, 0x2661},
{0x2663, 0x2665}, {0x2667, 0x266A}, {0x266C, 0x266D},
{0x266F, 0x266F}, {0x269E, 0x269F}, {0x26BF, 0x26BF},
{0x26C6, 0x26CD}, {0x26CF, 0x26D3}, {0x26D5, 0x26E1},
{0x26E3, 0x26E3}, {0x26E8, 0x26E9}, {0x26EB, 0x26F1},
{0x26F4, 0x26F4}, {0x26F6, 0x26F9}, {0x26FB, 0x26FC},
{0x26FE, 0x26FF}, {0x273D, 0x273D}, {0x2776, 0x277F},
{0x2B56, 0x2B59}, {0x3248, 0x324F}, {0xE000, 0xF8FF},
{0xFE00, 0xFE0F}, {0xFFFD, 0xFFFD}, {0x1F100, 0x1F10A},
{0x1F110, 0x1F12D}, {0x1F130, 0x1F169}, {0x1F170, 0x1F18D},
{0x1F18F, 0x1F190}, {0x1F19B, 0x1F1AC}, {0xE0100, 0xE01EF},
{0xF0000, 0xFFFFD}, {0x100000, 0x10FFFD},
}
var emoji = table{
{0x203C, 0x203C}, {0x2049, 0x2049}, {0x2122, 0x2122},
{0x2139, 0x2139}, {0x2194, 0x2199}, {0x21A9, 0x21AA},
{0x231A, 0x231B}, {0x2328, 0x2328}, {0x23CF, 0x23CF},
{0x23E9, 0x23F3}, {0x23F8, 0x23FA}, {0x24C2, 0x24C2},
{0x25AA, 0x25AB}, {0x25B6, 0x25B6}, {0x25C0, 0x25C0},
{0x25FB, 0x25FE}, {0x2600, 0x2604}, {0x260E, 0x260E},
{0x2611, 0x2611}, {0x2614, 0x2615}, {0x2618, 0x2618},
{0x261D, 0x261D}, {0x2620, 0x2620}, {0x2622, 0x2623},
{0x2626, 0x2626}, {0x262A, 0x262A}, {0x262E, 0x262F},
{0x2638, 0x263A}, {0x2640, 0x2640}, {0x2642, 0x2642},
{0x2648, 0x2653}, {0x265F, 0x2660}, {0x2663, 0x2663},
{0x2665, 0x2666}, {0x2668, 0x2668}, {0x267B, 0x267B},
{0x267E, 0x267F}, {0x2692, 0x2697}, {0x2699, 0x2699},
{0x269B, 0x269C}, {0x26A0, 0x26A1}, {0x26AA, 0x26AB},
{0x26B0, 0x26B1}, {0x26BD, 0x26BE}, {0x26C4, 0x26C5},
{0x26C8, 0x26C8}, {0x26CE, 0x26CF}, {0x26D1, 0x26D1},
{0x26D3, 0x26D4}, {0x26E9, 0x26EA}, {0x26F0, 0x26F5},
{0x26F7, 0x26FA}, {0x26FD, 0x26FD}, {0x2702, 0x2702},
{0x2705, 0x2705}, {0x2708, 0x270D}, {0x270F, 0x270F},
{0x2712, 0x2712}, {0x2714, 0x2714}, {0x2716, 0x2716},
{0x271D, 0x271D}, {0x2721, 0x2721}, {0x2728, 0x2728},
{0x2733, 0x2734}, {0x2744, 0x2744}, {0x2747, 0x2747},
{0x274C, 0x274C}, {0x274E, 0x274E}, {0x2753, 0x2755},
{0x2757, 0x2757}, {0x2763, 0x2764}, {0x2795, 0x2797},
{0x27A1, 0x27A1}, {0x27B0, 0x27B0}, {0x27BF, 0x27BF},
{0x2934, 0x2935}, {0x2B05, 0x2B07}, {0x2B1B, 0x2B1C},
{0x2B50, 0x2B50}, {0x2B55, 0x2B55}, {0x3030, 0x3030},
{0x303D, 0x303D}, {0x3297, 0x3297}, {0x3299, 0x3299},
{0x1F004, 0x1F004}, {0x1F0CF, 0x1F0CF}, {0x1F170, 0x1F171},
{0x1F17E, 0x1F17F}, {0x1F18E, 0x1F18E}, {0x1F191, 0x1F19A},
{0x1F1E6, 0x1F1FF}, {0x1F201, 0x1F202}, {0x1F21A, 0x1F21A},
{0x1F22F, 0x1F22F}, {0x1F232, 0x1F23A}, {0x1F250, 0x1F251},
{0x1F300, 0x1F321}, {0x1F324, 0x1F393}, {0x1F396, 0x1F397},
{0x1F399, 0x1F39B}, {0x1F39E, 0x1F3F0}, {0x1F3F3, 0x1F3F5},
{0x1F3F7, 0x1F4FD}, {0x1F4FF, 0x1F53D}, {0x1F549, 0x1F54E},
{0x1F550, 0x1F567}, {0x1F56F, 0x1F570}, {0x1F573, 0x1F57A},
{0x1F587, 0x1F587}, {0x1F58A, 0x1F58D}, {0x1F590, 0x1F590},
{0x1F595, 0x1F596}, {0x1F5A4, 0x1F5A5}, {0x1F5A8, 0x1F5A8},
{0x1F5B1, 0x1F5B2}, {0x1F5BC, 0x1F5BC}, {0x1F5C2, 0x1F5C4},
{0x1F5D1, 0x1F5D3}, {0x1F5DC, 0x1F5DE}, {0x1F5E1, 0x1F5E1},
{0x1F5E3, 0x1F5E3}, {0x1F5E8, 0x1F5E8}, {0x1F5EF, 0x1F5EF},
{0x1F5F3, 0x1F5F3}, {0x1F5FA, 0x1F64F}, {0x1F680, 0x1F6C5},
{0x1F6CB, 0x1F6D2}, {0x1F6E0, 0x1F6E5}, {0x1F6E9, 0x1F6E9},
{0x1F6EB, 0x1F6EC}, {0x1F6F0, 0x1F6F0}, {0x1F6F3, 0x1F6F9},
{0x1F910, 0x1F93A}, {0x1F93C, 0x1F93E}, {0x1F940, 0x1F945},
{0x1F947, 0x1F970}, {0x1F973, 0x1F976}, {0x1F97A, 0x1F97A},
{0x1F97C, 0x1F9A2}, {0x1F9B0, 0x1F9B9}, {0x1F9C0, 0x1F9C2},
{0x1F9D0, 0x1F9FF},
}
var notassigned = table{
{0x0378, 0x0379}, {0x0380, 0x0383}, {0x038B, 0x038B},
{0x038D, 0x038D}, {0x03A2, 0x03A2}, {0x0530, 0x0530},
{0x0557, 0x0558}, {0x0560, 0x0560}, {0x0588, 0x0588},
{0x058B, 0x058C}, {0x0590, 0x0590}, {0x05C8, 0x05CF},
{0x05EB, 0x05EF}, {0x05F5, 0x05FF}, {0x061D, 0x061D},
{0x070E, 0x070E}, {0x074B, 0x074C}, {0x07B2, 0x07BF},
{0x07FB, 0x07FF}, {0x082E, 0x082F}, {0x083F, 0x083F},
{0x085C, 0x085D}, {0x085F, 0x089F}, {0x08B5, 0x08B5},
{0x08BE, 0x08D3}, {0x0984, 0x0984}, {0x098D, 0x098E},
{0x0991, 0x0992}, {0x09A9, 0x09A9}, {0x09B1, 0x09B1},
{0x09B3, 0x09B5}, {0x09BA, 0x09BB}, {0x09C5, 0x09C6},
{0x09C9, 0x09CA}, {0x09CF, 0x09D6}, {0x09D8, 0x09DB},
{0x09DE, 0x09DE}, {0x09E4, 0x09E5}, {0x09FC, 0x0A00},
{0x0A04, 0x0A04}, {0x0A0B, 0x0A0E}, {0x0A11, 0x0A12},
{0x0A29, 0x0A29}, {0x0A31, 0x0A31}, {0x0A34, 0x0A34},
{0x0A37, 0x0A37}, {0x0A3A, 0x0A3B}, {0x0A3D, 0x0A3D},
{0x0A43, 0x0A46}, {0x0A49, 0x0A4A}, {0x0A4E, 0x0A50},
{0x0A52, 0x0A58}, {0x0A5D, 0x0A5D}, {0x0A5F, 0x0A65},
{0x0A76, 0x0A80}, {0x0A84, 0x0A84}, {0x0A8E, 0x0A8E},
{0x0A92, 0x0A92}, {0x0AA9, 0x0AA9}, {0x0AB1, 0x0AB1},
{0x0AB4, 0x0AB4}, {0x0ABA, 0x0ABB}, {0x0AC6, 0x0AC6},
{0x0ACA, 0x0ACA}, {0x0ACE, 0x0ACF}, {0x0AD1, 0x0ADF},
{0x0AE4, 0x0AE5}, {0x0AF2, 0x0AF8}, {0x0AFA, 0x0B00},
{0x0B04, 0x0B04}, {0x0B0D, 0x0B0E}, {0x0B11, 0x0B12},
{0x0B29, 0x0B29}, {0x0B31, 0x0B31}, {0x0B34, 0x0B34},
{0x0B3A, 0x0B3B}, {0x0B45, 0x0B46}, {0x0B49, 0x0B4A},
{0x0B4E, 0x0B55}, {0x0B58, 0x0B5B}, {0x0B5E, 0x0B5E},
{0x0B64, 0x0B65}, {0x0B78, 0x0B81}, {0x0B84, 0x0B84},
{0x0B8B, 0x0B8D}, {0x0B91, 0x0B91}, {0x0B96, 0x0B98},
{0x0B9B, 0x0B9B}, {0x0B9D, 0x0B9D}, {0x0BA0, 0x0BA2},
{0x0BA5, 0x0BA7}, {0x0BAB, 0x0BAD}, {0x0BBA, 0x0BBD},
{0x0BC3, 0x0BC5}, {0x0BC9, 0x0BC9}, {0x0BCE, 0x0BCF},
{0x0BD1, 0x0BD6}, {0x0BD8, 0x0BE5}, {0x0BFB, 0x0BFF},
{0x0C04, 0x0C04}, {0x0C0D, 0x0C0D}, {0x0C11, 0x0C11},
{0x0C29, 0x0C29}, {0x0C3A, 0x0C3C}, {0x0C45, 0x0C45},
{0x0C49, 0x0C49}, {0x0C4E, 0x0C54}, {0x0C57, 0x0C57},
{0x0C5B, 0x0C5F}, {0x0C64, 0x0C65}, {0x0C70, 0x0C77},
{0x0C84, 0x0C84}, {0x0C8D, 0x0C8D}, {0x0C91, 0x0C91},
{0x0CA9, 0x0CA9}, {0x0CB4, 0x0CB4}, {0x0CBA, 0x0CBB},
{0x0CC5, 0x0CC5}, {0x0CC9, 0x0CC9}, {0x0CCE, 0x0CD4},
{0x0CD7, 0x0CDD}, {0x0CDF, 0x0CDF}, {0x0CE4, 0x0CE5},
{0x0CF0, 0x0CF0}, {0x0CF3, 0x0D00}, {0x0D04, 0x0D04},
{0x0D0D, 0x0D0D}, {0x0D11, 0x0D11}, {0x0D3B, 0x0D3C},
{0x0D45, 0x0D45}, {0x0D49, 0x0D49}, {0x0D50, 0x0D53},
{0x0D64, 0x0D65}, {0x0D80, 0x0D81}, {0x0D84, 0x0D84},
{0x0D97, 0x0D99}, {0x0DB2, 0x0DB2}, {0x0DBC, 0x0DBC},
{0x0DBE, 0x0DBF}, {0x0DC7, 0x0DC9}, {0x0DCB, 0x0DCE},
{0x0DD5, 0x0DD5}, {0x0DD7, 0x0DD7}, {0x0DE0, 0x0DE5},
{0x0DF0, 0x0DF1}, {0x0DF5, 0x0E00}, {0x0E3B, 0x0E3E},
{0x0E5C, 0x0E80}, {0x0E83, 0x0E83}, {0x0E85, 0x0E86},
{0x0E89, 0x0E89}, {0x0E8B, 0x0E8C}, {0x0E8E, 0x0E93},
{0x0E98, 0x0E98}, {0x0EA0, 0x0EA0}, {0x0EA4, 0x0EA4},
{0x0EA6, 0x0EA6}, {0x0EA8, 0x0EA9}, {0x0EAC, 0x0EAC},
{0x0EBA, 0x0EBA}, {0x0EBE, 0x0EBF}, {0x0EC5, 0x0EC5},
{0x0EC7, 0x0EC7}, {0x0ECE, 0x0ECF}, {0x0EDA, 0x0EDB},
{0x0EE0, 0x0EFF}, {0x0F48, 0x0F48}, {0x0F6D, 0x0F70},
{0x0F98, 0x0F98}, {0x0FBD, 0x0FBD}, {0x0FCD, 0x0FCD},
{0x0FDB, 0x0FFF}, {0x10C6, 0x10C6}, {0x10C8, 0x10CC},
{0x10CE, 0x10CF}, {0x1249, 0x1249}, {0x124E, 0x124F},
{0x1257, 0x1257}, {0x1259, 0x1259}, {0x125E, 0x125F},
{0x1289, 0x1289}, {0x128E, 0x128F}, {0x12B1, 0x12B1},
{0x12B6, 0x12B7}, {0x12BF, 0x12BF}, {0x12C1, 0x12C1},
{0x12C6, 0x12C7}, {0x12D7, 0x12D7}, {0x1311, 0x1311},
{0x1316, 0x1317}, {0x135B, 0x135C}, {0x137D, 0x137F},
{0x139A, 0x139F}, {0x13F6, 0x13F7}, {0x13FE, 0x13FF},
{0x169D, 0x169F}, {0x16F9, 0x16FF}, {0x170D, 0x170D},
{0x1715, 0x171F}, {0x1737, 0x173F}, {0x1754, 0x175F},
{0x176D, 0x176D}, {0x1771, 0x1771}, {0x1774, 0x177F},
{0x17DE, 0x17DF}, {0x17EA, 0x17EF}, {0x17FA, 0x17FF},
{0x180F, 0x180F}, {0x181A, 0x181F}, {0x1878, 0x187F},
{0x18AB, 0x18AF}, {0x18F6, 0x18FF}, {0x191F, 0x191F},
{0x192C, 0x192F}, {0x193C, 0x193F}, {0x1941, 0x1943},
{0x196E, 0x196F}, {0x1975, 0x197F}, {0x19AC, 0x19AF},
{0x19CA, 0x19CF}, {0x19DB, 0x19DD}, {0x1A1C, 0x1A1D},
{0x1A5F, 0x1A5F}, {0x1A7D, 0x1A7E}, {0x1A8A, 0x1A8F},
{0x1A9A, 0x1A9F}, {0x1AAE, 0x1AAF}, {0x1ABF, 0x1AFF},
{0x1B4C, 0x1B4F}, {0x1B7D, 0x1B7F}, {0x1BF4, 0x1BFB},
{0x1C38, 0x1C3A}, {0x1C4A, 0x1C4C}, {0x1C89, 0x1CBF},
{0x1CC8, 0x1CCF}, {0x1CF7, 0x1CF7}, {0x1CFA, 0x1CFF},
{0x1DF6, 0x1DFA}, {0x1F16, 0x1F17}, {0x1F1E, 0x1F1F},
{0x1F46, 0x1F47}, {0x1F4E, 0x1F4F}, {0x1F58, 0x1F58},
{0x1F5A, 0x1F5A}, {0x1F5C, 0x1F5C}, {0x1F5E, 0x1F5E},
{0x1F7E, 0x1F7F}, {0x1FB5, 0x1FB5}, {0x1FC5, 0x1FC5},
{0x1FD4, 0x1FD5}, {0x1FDC, 0x1FDC}, {0x1FF0, 0x1FF1},
{0x1FF5, 0x1FF5}, {0x1FFF, 0x1FFF}, {0x2065, 0x2065},
{0x2072, 0x2073}, {0x208F, 0x208F}, {0x209D, 0x209F},
{0x20BF, 0x20CF}, {0x20F1, 0x20FF}, {0x218C, 0x218F},
{0x23FF, 0x23FF}, {0x2427, 0x243F}, {0x244B, 0x245F},
{0x2B74, 0x2B75}, {0x2B96, 0x2B97}, {0x2BBA, 0x2BBC},
{0x2BC9, 0x2BC9}, {0x2BD2, 0x2BEB}, {0x2BF0, 0x2BFF},
{0x2C2F, 0x2C2F}, {0x2C5F, 0x2C5F}, {0x2CF4, 0x2CF8},
{0x2D26, 0x2D26}, {0x2D28, 0x2D2C}, {0x2D2E, 0x2D2F},
{0x2D68, 0x2D6E}, {0x2D71, 0x2D7E}, {0x2D97, 0x2D9F},
{0x2DA7, 0x2DA7}, {0x2DAF, 0x2DAF}, {0x2DB7, 0x2DB7},
{0x2DBF, 0x2DBF}, {0x2DC7, 0x2DC7}, {0x2DCF, 0x2DCF},
{0x2DD7, 0x2DD7}, {0x2DDF, 0x2DDF}, {0x2E45, 0x2E7F},
{0x2E9A, 0x2E9A}, {0x2EF4, 0x2EFF}, {0x2FD6, 0x2FEF},
{0x2FFC, 0x2FFF}, {0x3040, 0x3040}, {0x3097, 0x3098},
{0x3100, 0x3104}, {0x312E, 0x3130}, {0x318F, 0x318F},
{0x31BB, 0x31BF}, {0x31E4, 0x31EF}, {0x321F, 0x321F},
{0x32FF, 0x32FF}, {0x4DB6, 0x4DBF}, {0x9FD6, 0x9FFF},
{0xA48D, 0xA48F}, {0xA4C7, 0xA4CF}, {0xA62C, 0xA63F},
{0xA6F8, 0xA6FF}, {0xA7AF, 0xA7AF}, {0xA7B8, 0xA7F6},
{0xA82C, 0xA82F}, {0xA83A, 0xA83F}, {0xA878, 0xA87F},
{0xA8C6, 0xA8CD}, {0xA8DA, 0xA8DF}, {0xA8FE, 0xA8FF},
{0xA954, 0xA95E}, {0xA97D, 0xA97F}, {0xA9CE, 0xA9CE},
{0xA9DA, 0xA9DD}, {0xA9FF, 0xA9FF}, {0xAA37, 0xAA3F},
{0xAA4E, 0xAA4F}, {0xAA5A, 0xAA5B}, {0xAAC3, 0xAADA},
{0xAAF7, 0xAB00}, {0xAB07, 0xAB08}, {0xAB0F, 0xAB10},
{0xAB17, 0xAB1F}, {0xAB27, 0xAB27}, {0xAB2F, 0xAB2F},
{0xAB66, 0xAB6F}, {0xABEE, 0xABEF}, {0xABFA, 0xABFF},
{0xD7A4, 0xD7AF}, {0xD7C7, 0xD7CA}, {0xD7FC, 0xD7FF},
{0xFA6E, 0xFA6F}, {0xFADA, 0xFAFF}, {0xFB07, 0xFB12},
{0xFB18, 0xFB1C}, {0xFB37, 0xFB37}, {0xFB3D, 0xFB3D},
{0xFB3F, 0xFB3F}, {0xFB42, 0xFB42}, {0xFB45, 0xFB45},
{0xFBC2, 0xFBD2}, {0xFD40, 0xFD4F}, {0xFD90, 0xFD91},
{0xFDC8, 0xFDEF}, {0xFDFE, 0xFDFF}, {0xFE1A, 0xFE1F},
{0xFE53, 0xFE53}, {0xFE67, 0xFE67}, {0xFE6C, 0xFE6F},
{0xFE75, 0xFE75}, {0xFEFD, 0xFEFE}, {0xFF00, 0xFF00},
{0xFFBF, 0xFFC1}, {0xFFC8, 0xFFC9}, {0xFFD0, 0xFFD1},
{0xFFD8, 0xFFD9}, {0xFFDD, 0xFFDF}, {0xFFE7, 0xFFE7},
{0xFFEF, 0xFFF8}, {0xFFFE, 0xFFFF}, {0x1000C, 0x1000C},
{0x10027, 0x10027}, {0x1003B, 0x1003B}, {0x1003E, 0x1003E},
{0x1004E, 0x1004F}, {0x1005E, 0x1007F}, {0x100FB, 0x100FF},
{0x10103, 0x10106}, {0x10134, 0x10136}, {0x1018F, 0x1018F},
{0x1019C, 0x1019F}, {0x101A1, 0x101CF}, {0x101FE, 0x1027F},
{0x1029D, 0x1029F}, {0x102D1, 0x102DF}, {0x102FC, 0x102FF},
{0x10324, 0x1032F}, {0x1034B, 0x1034F}, {0x1037B, 0x1037F},
{0x1039E, 0x1039E}, {0x103C4, 0x103C7}, {0x103D6, 0x103FF},
{0x1049E, 0x1049F}, {0x104AA, 0x104AF}, {0x104D4, 0x104D7},
{0x104FC, 0x104FF}, {0x10528, 0x1052F}, {0x10564, 0x1056E},
{0x10570, 0x105FF}, {0x10737, 0x1073F}, {0x10756, 0x1075F},
{0x10768, 0x107FF}, {0x10806, 0x10807}, {0x10809, 0x10809},
{0x10836, 0x10836}, {0x10839, 0x1083B}, {0x1083D, 0x1083E},
{0x10856, 0x10856}, {0x1089F, 0x108A6}, {0x108B0, 0x108DF},
{0x108F3, 0x108F3}, {0x108F6, 0x108FA}, {0x1091C, 0x1091E},
{0x1093A, 0x1093E}, {0x10940, 0x1097F}, {0x109B8, 0x109BB},
{0x109D0, 0x109D1}, {0x10A04, 0x10A04}, {0x10A07, 0x10A0B},
{0x10A14, 0x10A14}, {0x10A18, 0x10A18}, {0x10A34, 0x10A37},
{0x10A3B, 0x10A3E}, {0x10A48, 0x10A4F}, {0x10A59, 0x10A5F},
{0x10AA0, 0x10ABF}, {0x10AE7, 0x10AEA}, {0x10AF7, 0x10AFF},
{0x10B36, 0x10B38}, {0x10B56, 0x10B57}, {0x10B73, 0x10B77},
{0x10B92, 0x10B98}, {0x10B9D, 0x10BA8}, {0x10BB0, 0x10BFF},
{0x10C49, 0x10C7F}, {0x10CB3, 0x10CBF}, {0x10CF3, 0x10CF9},
{0x10D00, 0x10E5F}, {0x10E7F, 0x10FFF}, {0x1104E, 0x11051},
{0x11070, 0x1107E}, {0x110C2, 0x110CF}, {0x110E9, 0x110EF},
{0x110FA, 0x110FF}, {0x11135, 0x11135}, {0x11144, 0x1114F},
{0x11177, 0x1117F}, {0x111CE, 0x111CF}, {0x111E0, 0x111E0},
{0x111F5, 0x111FF}, {0x11212, 0x11212}, {0x1123F, 0x1127F},
{0x11287, 0x11287}, {0x11289, 0x11289}, {0x1128E, 0x1128E},
{0x1129E, 0x1129E}, {0x112AA, 0x112AF}, {0x112EB, 0x112EF},
{0x112FA, 0x112FF}, {0x11304, 0x11304}, {0x1130D, 0x1130E},
{0x11311, 0x11312}, {0x11329, 0x11329}, {0x11331, 0x11331},
{0x11334, 0x11334}, {0x1133A, 0x1133B}, {0x11345, 0x11346},
{0x11349, 0x1134A}, {0x1134E, 0x1134F}, {0x11351, 0x11356},
{0x11358, 0x1135C}, {0x11364, 0x11365}, {0x1136D, 0x1136F},
{0x11375, 0x113FF}, {0x1145A, 0x1145A}, {0x1145C, 0x1145C},
{0x1145E, 0x1147F}, {0x114C8, 0x114CF}, {0x114DA, 0x1157F},
{0x115B6, 0x115B7}, {0x115DE, 0x115FF}, {0x11645, 0x1164F},
{0x1165A, 0x1165F}, {0x1166D, 0x1167F}, {0x116B8, 0x116BF},
{0x116CA, 0x116FF}, {0x1171A, 0x1171C}, {0x1172C, 0x1172F},
{0x11740, 0x1189F}, {0x118F3, 0x118FE}, {0x11900, 0x11ABF},
{0x11AF9, 0x11BFF}, {0x11C09, 0x11C09}, {0x11C37, 0x11C37},
{0x11C46, 0x11C4F}, {0x11C6D, 0x11C6F}, {0x11C90, 0x11C91},
{0x11CA8, 0x11CA8}, {0x11CB7, 0x11FFF}, {0x1239A, 0x123FF},
{0x1246F, 0x1246F}, {0x12475, 0x1247F}, {0x12544, 0x12FFF},
{0x1342F, 0x143FF}, {0x14647, 0x167FF}, {0x16A39, 0x16A3F},
{0x16A5F, 0x16A5F}, {0x16A6A, 0x16A6D}, {0x16A70, 0x16ACF},
{0x16AEE, 0x16AEF}, {0x16AF6, 0x16AFF}, {0x16B46, 0x16B4F},
{0x16B5A, 0x16B5A}, {0x16B62, 0x16B62}, {0x16B78, 0x16B7C},
{0x16B90, 0x16EFF}, {0x16F45, 0x16F4F}, {0x16F7F, 0x16F8E},
{0x16FA0, 0x16FDF}, {0x16FE1, 0x16FFF}, {0x187ED, 0x187FF},
{0x18AF3, 0x1AFFF}, {0x1B002, 0x1BBFF}, {0x1BC6B, 0x1BC6F},
{0x1BC7D, 0x1BC7F}, {0x1BC89, 0x1BC8F}, {0x1BC9A, 0x1BC9B},
{0x1BCA4, 0x1CFFF}, {0x1D0F6, 0x1D0FF}, {0x1D127, 0x1D128},
{0x1D1E9, 0x1D1FF}, {0x1D246, 0x1D2FF}, {0x1D357, 0x1D35F},
{0x1D372, 0x1D3FF}, {0x1D455, 0x1D455}, {0x1D49D, 0x1D49D},
{0x1D4A0, 0x1D4A1}, {0x1D4A3, 0x1D4A4}, {0x1D4A7, 0x1D4A8},
{0x1D4AD, 0x1D4AD}, {0x1D4BA, 0x1D4BA}, {0x1D4BC, 0x1D4BC},
{0x1D4C4, 0x1D4C4}, {0x1D506, 0x1D506}, {0x1D50B, 0x1D50C},
{0x1D515, 0x1D515}, {0x1D51D, 0x1D51D}, {0x1D53A, 0x1D53A},
{0x1D53F, 0x1D53F}, {0x1D545, 0x1D545}, {0x1D547, 0x1D549},
{0x1D551, 0x1D551}, {0x1D6A6, 0x1D6A7}, {0x1D7CC, 0x1D7CD},
{0x1DA8C, 0x1DA9A}, {0x1DAA0, 0x1DAA0}, {0x1DAB0, 0x1DFFF},
{0x1E007, 0x1E007}, {0x1E019, 0x1E01A}, {0x1E022, 0x1E022},
{0x1E025, 0x1E025}, {0x1E02B, 0x1E7FF}, {0x1E8C5, 0x1E8C6},
{0x1E8D7, 0x1E8FF}, {0x1E94B, 0x1E94F}, {0x1E95A, 0x1E95D},
{0x1E960, 0x1EDFF}, {0x1EE04, 0x1EE04}, {0x1EE20, 0x1EE20},
{0x1EE23, 0x1EE23}, {0x1EE25, 0x1EE26}, {0x1EE28, 0x1EE28},
{0x1EE33, 0x1EE33}, {0x1EE38, 0x1EE38}, {0x1EE3A, 0x1EE3A},
{0x1EE3C, 0x1EE41}, {0x1EE43, 0x1EE46}, {0x1EE48, 0x1EE48},
{0x1EE4A, 0x1EE4A}, {0x1EE4C, 0x1EE4C}, {0x1EE50, 0x1EE50},
{0x1EE53, 0x1EE53}, {0x1EE55, 0x1EE56}, {0x1EE58, 0x1EE58},
{0x1EE5A, 0x1EE5A}, {0x1EE5C, 0x1EE5C}, {0x1EE5E, 0x1EE5E},
{0x1EE60, 0x1EE60}, {0x1EE63, 0x1EE63}, {0x1EE65, 0x1EE66},
{0x1EE6B, 0x1EE6B}, {0x1EE73, 0x1EE73}, {0x1EE78, 0x1EE78},
{0x1EE7D, 0x1EE7D}, {0x1EE7F, 0x1EE7F}, {0x1EE8A, 0x1EE8A},
{0x1EE9C, 0x1EEA0}, {0x1EEA4, 0x1EEA4}, {0x1EEAA, 0x1EEAA},
{0x1EEBC, 0x1EEEF}, {0x1EEF2, 0x1EFFF}, {0x1F02C, 0x1F02F},
{0x1F094, 0x1F09F}, {0x1F0AF, 0x1F0B0}, {0x1F0C0, 0x1F0C0},
{0x1F0D0, 0x1F0D0}, {0x1F0F6, 0x1F0FF}, {0x1F10D, 0x1F10F},
{0x1F12F, 0x1F12F}, {0x1F16C, 0x1F16F}, {0x1F1AD, 0x1F1E5},
{0x1F203, 0x1F20F}, {0x1F23C, 0x1F23F}, {0x1F249, 0x1F24F},
{0x1F252, 0x1F2FF}, {0x1F6D3, 0x1F6DF}, {0x1F6ED, 0x1F6EF},
{0x1F6F7, 0x1F6FF}, {0x1F774, 0x1F77F}, {0x1F7D5, 0x1F7FF},
{0x1F80C, 0x1F80F}, {0x1F848, 0x1F84F}, {0x1F85A, 0x1F85F},
{0x1F888, 0x1F88F}, {0x1F8AE, 0x1F90F}, {0x1F91F, 0x1F91F},
{0x1F928, 0x1F92F}, {0x1F931, 0x1F932}, {0x1F93F, 0x1F93F},
{0x1F94C, 0x1F94F}, {0x1F95F, 0x1F97F}, {0x1F992, 0x1F9BF},
{0x1F9C1, 0x1FFFF}, {0x2A6D7, 0x2A6FF}, {0x2B735, 0x2B73F},
{0x2B81E, 0x2B81F}, {0x2CEA2, 0x2F7FF}, {0x2FA1E, 0xE0000},
{0xE0002, 0xE001F}, {0xE0080, 0xE00FF}, {0xE01F0, 0xEFFFF},
{0xFFFFE, 0xFFFFF},
}
var neutral = table{
{0x0000, 0x001F}, {0x007F, 0x00A0}, {0x00A9, 0x00A9},
{0x00AB, 0x00AB}, {0x00B5, 0x00B5}, {0x00BB, 0x00BB},
{0x00C0, 0x00C5}, {0x00C7, 0x00CF}, {0x00D1, 0x00D6},
{0x00D9, 0x00DD}, {0x00E2, 0x00E5}, {0x00E7, 0x00E7},
{0x00EB, 0x00EB}, {0x00EE, 0x00EF}, {0x00F1, 0x00F1},
{0x00F4, 0x00F6}, {0x00FB, 0x00FB}, {0x00FD, 0x00FD},
{0x00FF, 0x0100}, {0x0102, 0x0110}, {0x0112, 0x0112},
{0x0114, 0x011A}, {0x011C, 0x0125}, {0x0128, 0x012A},
{0x012C, 0x0130}, {0x0134, 0x0137}, {0x0139, 0x013E},
{0x0143, 0x0143}, {0x0145, 0x0147}, {0x014C, 0x014C},
{0x014E, 0x0151}, {0x0154, 0x0165}, {0x0168, 0x016A},
{0x016C, 0x01CD}, {0x01CF, 0x01CF}, {0x01D1, 0x01D1},
{0x01D3, 0x01D3}, {0x01D5, 0x01D5}, {0x01D7, 0x01D7},
{0x01D9, 0x01D9}, {0x01DB, 0x01DB}, {0x01DD, 0x0250},
{0x0252, 0x0260}, {0x0262, 0x02C3}, {0x02C5, 0x02C6},
{0x02C8, 0x02C8}, {0x02CC, 0x02CC}, {0x02CE, 0x02CF},
{0x02D1, 0x02D7}, {0x02DC, 0x02DC}, {0x02DE, 0x02DE},
{0x02E0, 0x02FF}, {0x0370, 0x0377}, {0x037A, 0x037F},
{0x0384, 0x038A}, {0x038C, 0x038C}, {0x038E, 0x0390},
{0x03AA, 0x03B0}, {0x03C2, 0x03C2}, {0x03CA, 0x0400},
{0x0402, 0x040F}, {0x0450, 0x0450}, {0x0452, 0x052F},
{0x0531, 0x0556}, {0x0559, 0x055F}, {0x0561, 0x0587},
{0x0589, 0x058A}, {0x058D, 0x058F}, {0x0591, 0x05C7},
{0x05D0, 0x05EA}, {0x05F0, 0x05F4}, {0x0600, 0x061C},
{0x061E, 0x070D}, {0x070F, 0x074A}, {0x074D, 0x07B1},
{0x07C0, 0x07FA}, {0x0800, 0x082D}, {0x0830, 0x083E},
{0x0840, 0x085B}, {0x085E, 0x085E}, {0x08A0, 0x08B4},
{0x08B6, 0x08BD}, {0x08D4, 0x0983}, {0x0985, 0x098C},
{0x098F, 0x0990}, {0x0993, 0x09A8}, {0x09AA, 0x09B0},
{0x09B2, 0x09B2}, {0x09B6, 0x09B9}, {0x09BC, 0x09C4},
{0x09C7, 0x09C8}, {0x09CB, 0x09CE}, {0x09D7, 0x09D7},
{0x09DC, 0x09DD}, {0x09DF, 0x09E3}, {0x09E6, 0x09FB},
{0x0A01, 0x0A03}, {0x0A05, 0x0A0A}, {0x0A0F, 0x0A10},
{0x0A13, 0x0A28}, {0x0A2A, 0x0A30}, {0x0A32, 0x0A33},
{0x0A35, 0x0A36}, {0x0A38, 0x0A39}, {0x0A3C, 0x0A3C},
{0x0A3E, 0x0A42}, {0x0A47, 0x0A48}, {0x0A4B, 0x0A4D},
{0x0A51, 0x0A51}, {0x0A59, 0x0A5C}, {0x0A5E, 0x0A5E},
{0x0A66, 0x0A75}, {0x0A81, 0x0A83}, {0x0A85, 0x0A8D},
{0x0A8F, 0x0A91}, {0x0A93, 0x0AA8}, {0x0AAA, 0x0AB0},
{0x0AB2, 0x0AB3}, {0x0AB5, 0x0AB9}, {0x0ABC, 0x0AC5},
{0x0AC7, 0x0AC9}, {0x0ACB, 0x0ACD}, {0x0AD0, 0x0AD0},
{0x0AE0, 0x0AE3}, {0x0AE6, 0x0AF1}, {0x0AF9, 0x0AF9},
{0x0B01, 0x0B03}, {0x0B05, 0x0B0C}, {0x0B0F, 0x0B10},
{0x0B13, 0x0B28}, {0x0B2A, 0x0B30}, {0x0B32, 0x0B33},
{0x0B35, 0x0B39}, {0x0B3C, 0x0B44}, {0x0B47, 0x0B48},
{0x0B4B, 0x0B4D}, {0x0B56, 0x0B57}, {0x0B5C, 0x0B5D},
{0x0B5F, 0x0B63}, {0x0B66, 0x0B77}, {0x0B82, 0x0B83},
{0x0B85, 0x0B8A}, {0x0B8E, 0x0B90}, {0x0B92, 0x0B95},
{0x0B99, 0x0B9A}, {0x0B9C, 0x0B9C}, {0x0B9E, 0x0B9F},
{0x0BA3, 0x0BA4}, {0x0BA8, 0x0BAA}, {0x0BAE, 0x0BB9},
{0x0BBE, 0x0BC2}, {0x0BC6, 0x0BC8}, {0x0BCA, 0x0BCD},
{0x0BD0, 0x0BD0}, {0x0BD7, 0x0BD7}, {0x0BE6, 0x0BFA},
{0x0C00, 0x0C03}, {0x0C05, 0x0C0C}, {0x0C0E, 0x0C10},
{0x0C12, 0x0C28}, {0x0C2A, 0x0C39}, {0x0C3D, 0x0C44},
{0x0C46, 0x0C48}, {0x0C4A, 0x0C4D}, {0x0C55, 0x0C56},
{0x0C58, 0x0C5A}, {0x0C60, 0x0C63}, {0x0C66, 0x0C6F},
{0x0C78, 0x0C83}, {0x0C85, 0x0C8C}, {0x0C8E, 0x0C90},
{0x0C92, 0x0CA8}, {0x0CAA, 0x0CB3}, {0x0CB5, 0x0CB9},
{0x0CBC, 0x0CC4}, {0x0CC6, 0x0CC8}, {0x0CCA, 0x0CCD},
{0x0CD5, 0x0CD6}, {0x0CDE, 0x0CDE}, {0x0CE0, 0x0CE3},
{0x0CE6, 0x0CEF}, {0x0CF1, 0x0CF2}, {0x0D01, 0x0D03},
{0x0D05, 0x0D0C}, {0x0D0E, 0x0D10}, {0x0D12, 0x0D3A},
{0x0D3D, 0x0D44}, {0x0D46, 0x0D48}, {0x0D4A, 0x0D4F},
{0x0D54, 0x0D63}, {0x0D66, 0x0D7F}, {0x0D82, 0x0D83},
{0x0D85, 0x0D96}, {0x0D9A, 0x0DB1}, {0x0DB3, 0x0DBB},
{0x0DBD, 0x0DBD}, {0x0DC0, 0x0DC6}, {0x0DCA, 0x0DCA},
{0x0DCF, 0x0DD4}, {0x0DD6, 0x0DD6}, {0x0DD8, 0x0DDF},
{0x0DE6, 0x0DEF}, {0x0DF2, 0x0DF4}, {0x0E01, 0x0E3A},
{0x0E3F, 0x0E5B}, {0x0E81, 0x0E82}, {0x0E84, 0x0E84},
{0x0E87, 0x0E88}, {0x0E8A, 0x0E8A}, {0x0E8D, 0x0E8D},
{0x0E94, 0x0E97}, {0x0E99, 0x0E9F}, {0x0EA1, 0x0EA3},
{0x0EA5, 0x0EA5}, {0x0EA7, 0x0EA7}, {0x0EAA, 0x0EAB},
{0x0EAD, 0x0EB9}, {0x0EBB, 0x0EBD}, {0x0EC0, 0x0EC4},
{0x0EC6, 0x0EC6}, {0x0EC8, 0x0ECD}, {0x0ED0, 0x0ED9},
{0x0EDC, 0x0EDF}, {0x0F00, 0x0F47}, {0x0F49, 0x0F6C},
{0x0F71, 0x0F97}, {0x0F99, 0x0FBC}, {0x0FBE, 0x0FCC},
{0x0FCE, 0x0FDA}, {0x1000, 0x10C5}, {0x10C7, 0x10C7},
{0x10CD, 0x10CD}, {0x10D0, 0x10FF}, {0x1160, 0x1248},
{0x124A, 0x124D}, {0x1250, 0x1256}, {0x1258, 0x1258},
{0x125A, 0x125D}, {0x1260, 0x1288}, {0x128A, 0x128D},
{0x1290, 0x12B0}, {0x12B2, 0x12B5}, {0x12B8, 0x12BE},
{0x12C0, 0x12C0}, {0x12C2, 0x12C5}, {0x12C8, 0x12D6},
{0x12D8, 0x1310}, {0x1312, 0x1315}, {0x1318, 0x135A},
{0x135D, 0x137C}, {0x1380, 0x1399}, {0x13A0, 0x13F5},
{0x13F8, 0x13FD}, {0x1400, 0x169C}, {0x16A0, 0x16F8},
{0x1700, 0x170C}, {0x170E, 0x1714}, {0x1720, 0x1736},
{0x1740, 0x1753}, {0x1760, 0x176C}, {0x176E, 0x1770},
{0x1772, 0x1773}, {0x1780, 0x17DD}, {0x17E0, 0x17E9},
{0x17F0, 0x17F9}, {0x1800, 0x180E}, {0x1810, 0x1819},
{0x1820, 0x1877}, {0x1880, 0x18AA}, {0x18B0, 0x18F5},
{0x1900, 0x191E}, {0x1920, 0x192B}, {0x1930, 0x193B},
{0x1940, 0x1940}, {0x1944, 0x196D}, {0x1970, 0x1974},
{0x1980, 0x19AB}, {0x19B0, 0x19C9}, {0x19D0, 0x19DA},
{0x19DE, 0x1A1B}, {0x1A1E, 0x1A5E}, {0x1A60, 0x1A7C},
{0x1A7F, 0x1A89}, {0x1A90, 0x1A99}, {0x1AA0, 0x1AAD},
{0x1AB0, 0x1ABE}, {0x1B00, 0x1B4B}, {0x1B50, 0x1B7C},
{0x1B80, 0x1BF3}, {0x1BFC, 0x1C37}, {0x1C3B, 0x1C49},
{0x1C4D, 0x1C88}, {0x1CC0, 0x1CC7}, {0x1CD0, 0x1CF6},
{0x1CF8, 0x1CF9}, {0x1D00, 0x1DF5}, {0x1DFB, 0x1F15},
{0x1F18, 0x1F1D}, {0x1F20, 0x1F45}, {0x1F48, 0x1F4D},
{0x1F50, 0x1F57}, {0x1F59, 0x1F59}, {0x1F5B, 0x1F5B},
{0x1F5D, 0x1F5D}, {0x1F5F, 0x1F7D}, {0x1F80, 0x1FB4},
{0x1FB6, 0x1FC4}, {0x1FC6, 0x1FD3}, {0x1FD6, 0x1FDB},
{0x1FDD, 0x1FEF}, {0x1FF2, 0x1FF4}, {0x1FF6, 0x1FFE},
{0x2000, 0x200F}, {0x2011, 0x2012}, {0x2017, 0x2017},
{0x201A, 0x201B}, {0x201E, 0x201F}, {0x2023, 0x2023},
{0x2028, 0x202F}, {0x2031, 0x2031}, {0x2034, 0x2034},
{0x2036, 0x203A}, {0x203C, 0x203D}, {0x203F, 0x2064},
{0x2066, 0x2071}, {0x2075, 0x207E}, {0x2080, 0x2080},
{0x2085, 0x208E}, {0x2090, 0x209C}, {0x20A0, 0x20A8},
{0x20AA, 0x20AB}, {0x20AD, 0x20BE}, {0x20D0, 0x20F0},
{0x2100, 0x2102}, {0x2104, 0x2104}, {0x2106, 0x2108},
{0x210A, 0x2112}, {0x2114, 0x2115}, {0x2117, 0x2120},
{0x2123, 0x2125}, {0x2127, 0x212A}, {0x212C, 0x2152},
{0x2155, 0x215A}, {0x215F, 0x215F}, {0x216C, 0x216F},
{0x217A, 0x2188}, {0x218A, 0x218B}, {0x219A, 0x21B7},
{0x21BA, 0x21D1}, {0x21D3, 0x21D3}, {0x21D5, 0x21E6},
{0x21E8, 0x21FF}, {0x2201, 0x2201}, {0x2204, 0x2206},
{0x2209, 0x220A}, {0x220C, 0x220E}, {0x2210, 0x2210},
{0x2212, 0x2214}, {0x2216, 0x2219}, {0x221B, 0x221C},
{0x2221, 0x2222}, {0x2224, 0x2224}, {0x2226, 0x2226},
{0x222D, 0x222D}, {0x222F, 0x2233}, {0x2238, 0x223B},
{0x223E, 0x2247}, {0x2249, 0x224B}, {0x224D, 0x2251},
{0x2253, 0x225F}, {0x2262, 0x2263}, {0x2268, 0x2269},
{0x226C, 0x226D}, {0x2270, 0x2281}, {0x2284, 0x2285},
{0x2288, 0x2294}, {0x2296, 0x2298}, {0x229A, 0x22A4},
{0x22A6, 0x22BE}, {0x22C0, 0x2311}, {0x2313, 0x2319},
{0x231C, 0x2328}, {0x232B, 0x23E8}, {0x23ED, 0x23EF},
{0x23F1, 0x23F2}, {0x23F4, 0x23FE}, {0x2400, 0x2426},
{0x2440, 0x244A}, {0x24EA, 0x24EA}, {0x254C, 0x254F},
{0x2574, 0x257F}, {0x2590, 0x2591}, {0x2596, 0x259F},
{0x25A2, 0x25A2}, {0x25AA, 0x25B1}, {0x25B4, 0x25B5},
{0x25B8, 0x25BB}, {0x25BE, 0x25BF}, {0x25C2, 0x25C5},
{0x25C9, 0x25CA}, {0x25CC, 0x25CD}, {0x25D2, 0x25E1},
{0x25E6, 0x25EE}, {0x25F0, 0x25FC}, {0x25FF, 0x2604},
{0x2607, 0x2608}, {0x260A, 0x260D}, {0x2610, 0x2613},
{0x2616, 0x261B}, {0x261D, 0x261D}, {0x261F, 0x263F},
{0x2641, 0x2641}, {0x2643, 0x2647}, {0x2654, 0x265F},
{0x2662, 0x2662}, {0x2666, 0x2666}, {0x266B, 0x266B},
{0x266E, 0x266E}, {0x2670, 0x267E}, {0x2680, 0x2692},
{0x2694, 0x269D}, {0x26A0, 0x26A0}, {0x26A2, 0x26A9},
{0x26AC, 0x26BC}, {0x26C0, 0x26C3}, {0x26E2, 0x26E2},
{0x26E4, 0x26E7}, {0x2700, 0x2704}, {0x2706, 0x2709},
{0x270C, 0x2727}, {0x2729, 0x273C}, {0x273E, 0x274B},
{0x274D, 0x274D}, {0x274F, 0x2752}, {0x2756, 0x2756},
{0x2758, 0x2775}, {0x2780, 0x2794}, {0x2798, 0x27AF},
{0x27B1, 0x27BE}, {0x27C0, 0x27E5}, {0x27EE, 0x2984},
{0x2987, 0x2B1A}, {0x2B1D, 0x2B4F}, {0x2B51, 0x2B54},
{0x2B5A, 0x2B73}, {0x2B76, 0x2B95}, {0x2B98, 0x2BB9},
{0x2BBD, 0x2BC8}, {0x2BCA, 0x2BD1}, {0x2BEC, 0x2BEF},
{0x2C00, 0x2C2E}, {0x2C30, 0x2C5E}, {0x2C60, 0x2CF3},
{0x2CF9, 0x2D25}, {0x2D27, 0x2D27}, {0x2D2D, 0x2D2D},
{0x2D30, 0x2D67}, {0x2D6F, 0x2D70}, {0x2D7F, 0x2D96},
{0x2DA0, 0x2DA6}, {0x2DA8, 0x2DAE}, {0x2DB0, 0x2DB6},
{0x2DB8, 0x2DBE}, {0x2DC0, 0x2DC6}, {0x2DC8, 0x2DCE},
{0x2DD0, 0x2DD6}, {0x2DD8, 0x2DDE}, {0x2DE0, 0x2E44},
{0x303F, 0x303F}, {0x4DC0, 0x4DFF}, {0xA4D0, 0xA62B},
{0xA640, 0xA6F7}, {0xA700, 0xA7AE}, {0xA7B0, 0xA7B7},
{0xA7F7, 0xA82B}, {0xA830, 0xA839}, {0xA840, 0xA877},
{0xA880, 0xA8C5}, {0xA8CE, 0xA8D9}, {0xA8E0, 0xA8FD},
{0xA900, 0xA953}, {0xA95F, 0xA95F}, {0xA980, 0xA9CD},
{0xA9CF, 0xA9D9}, {0xA9DE, 0xA9FE}, {0xAA00, 0xAA36},
{0xAA40, 0xAA4D}, {0xAA50, 0xAA59}, {0xAA5C, 0xAAC2},
{0xAADB, 0xAAF6}, {0xAB01, 0xAB06}, {0xAB09, 0xAB0E},
{0xAB11, 0xAB16}, {0xAB20, 0xAB26}, {0xAB28, 0xAB2E},
{0xAB30, 0xAB65}, {0xAB70, 0xABED}, {0xABF0, 0xABF9},
{0xD7B0, 0xD7C6}, {0xD7CB, 0xD7FB}, {0xD800, 0xDFFF},
{0xFB00, 0xFB06}, {0xFB13, 0xFB17}, {0xFB1D, 0xFB36},
{0xFB38, 0xFB3C}, {0xFB3E, 0xFB3E}, {0xFB40, 0xFB41},
{0xFB43, 0xFB44}, {0xFB46, 0xFBC1}, {0xFBD3, 0xFD3F},
{0xFD50, 0xFD8F}, {0xFD92, 0xFDC7}, {0xFDF0, 0xFDFD},
{0xFE20, 0xFE2F}, {0xFE70, 0xFE74}, {0xFE76, 0xFEFC},
{0xFEFF, 0xFEFF}, {0xFFF9, 0xFFFC}, {0x10000, 0x1000B},
{0x1000D, 0x10026}, {0x10028, 0x1003A}, {0x1003C, 0x1003D},
{0x1003F, 0x1004D}, {0x10050, 0x1005D}, {0x10080, 0x100FA},
{0x10100, 0x10102}, {0x10107, 0x10133}, {0x10137, 0x1018E},
{0x10190, 0x1019B}, {0x101A0, 0x101A0}, {0x101D0, 0x101FD},
{0x10280, 0x1029C}, {0x102A0, 0x102D0}, {0x102E0, 0x102FB},
{0x10300, 0x10323}, {0x10330, 0x1034A}, {0x10350, 0x1037A},
{0x10380, 0x1039D}, {0x1039F, 0x103C3}, {0x103C8, 0x103D5},
{0x10400, 0x1049D}, {0x104A0, 0x104A9}, {0x104B0, 0x104D3},
{0x104D8, 0x104FB}, {0x10500, 0x10527}, {0x10530, 0x10563},
{0x1056F, 0x1056F}, {0x10600, 0x10736}, {0x10740, 0x10755},
{0x10760, 0x10767}, {0x10800, 0x10805}, {0x10808, 0x10808},
{0x1080A, 0x10835}, {0x10837, 0x10838}, {0x1083C, 0x1083C},
{0x1083F, 0x10855}, {0x10857, 0x1089E}, {0x108A7, 0x108AF},
{0x108E0, 0x108F2}, {0x108F4, 0x108F5}, {0x108FB, 0x1091B},
{0x1091F, 0x10939}, {0x1093F, 0x1093F}, {0x10980, 0x109B7},
{0x109BC, 0x109CF}, {0x109D2, 0x10A03}, {0x10A05, 0x10A06},
{0x10A0C, 0x10A13}, {0x10A15, 0x10A17}, {0x10A19, 0x10A33},
{0x10A38, 0x10A3A}, {0x10A3F, 0x10A47}, {0x10A50, 0x10A58},
{0x10A60, 0x10A9F}, {0x10AC0, 0x10AE6}, {0x10AEB, 0x10AF6},
{0x10B00, 0x10B35}, {0x10B39, 0x10B55}, {0x10B58, 0x10B72},
{0x10B78, 0x10B91}, {0x10B99, 0x10B9C}, {0x10BA9, 0x10BAF},
{0x10C00, 0x10C48}, {0x10C80, 0x10CB2}, {0x10CC0, 0x10CF2},
{0x10CFA, 0x10CFF}, {0x10E60, 0x10E7E}, {0x11000, 0x1104D},
{0x11052, 0x1106F}, {0x1107F, 0x110C1}, {0x110D0, 0x110E8},
{0x110F0, 0x110F9}, {0x11100, 0x11134}, {0x11136, 0x11143},
{0x11150, 0x11176}, {0x11180, 0x111CD}, {0x111D0, 0x111DF},
{0x111E1, 0x111F4}, {0x11200, 0x11211}, {0x11213, 0x1123E},
{0x11280, 0x11286}, {0x11288, 0x11288}, {0x1128A, 0x1128D},
{0x1128F, 0x1129D}, {0x1129F, 0x112A9}, {0x112B0, 0x112EA},
{0x112F0, 0x112F9}, {0x11300, 0x11303}, {0x11305, 0x1130C},
{0x1130F, 0x11310}, {0x11313, 0x11328}, {0x1132A, 0x11330},
{0x11332, 0x11333}, {0x11335, 0x11339}, {0x1133C, 0x11344},
{0x11347, 0x11348}, {0x1134B, 0x1134D}, {0x11350, 0x11350},
{0x11357, 0x11357}, {0x1135D, 0x11363}, {0x11366, 0x1136C},
{0x11370, 0x11374}, {0x11400, 0x11459}, {0x1145B, 0x1145B},
{0x1145D, 0x1145D}, {0x11480, 0x114C7}, {0x114D0, 0x114D9},
{0x11580, 0x115B5}, {0x115B8, 0x115DD}, {0x11600, 0x11644},
{0x11650, 0x11659}, {0x11660, 0x1166C}, {0x11680, 0x116B7},
{0x116C0, 0x116C9}, {0x11700, 0x11719}, {0x1171D, 0x1172B},
{0x11730, 0x1173F}, {0x118A0, 0x118F2}, {0x118FF, 0x118FF},
{0x11AC0, 0x11AF8}, {0x11C00, 0x11C08}, {0x11C0A, 0x11C36},
{0x11C38, 0x11C45}, {0x11C50, 0x11C6C}, {0x11C70, 0x11C8F},
{0x11C92, 0x11CA7}, {0x11CA9, 0x11CB6}, {0x12000, 0x12399},
{0x12400, 0x1246E}, {0x12470, 0x12474}, {0x12480, 0x12543},
{0x13000, 0x1342E}, {0x14400, 0x14646}, {0x16800, 0x16A38},
{0x16A40, 0x16A5E}, {0x16A60, 0x16A69}, {0x16A6E, 0x16A6F},
{0x16AD0, 0x16AED}, {0x16AF0, 0x16AF5}, {0x16B00, 0x16B45},
{0x16B50, 0x16B59}, {0x16B5B, 0x16B61}, {0x16B63, 0x16B77},
{0x16B7D, 0x16B8F}, {0x16F00, 0x16F44}, {0x16F50, 0x16F7E},
{0x16F8F, 0x16F9F}, {0x1BC00, 0x1BC6A}, {0x1BC70, 0x1BC7C},
{0x1BC80, 0x1BC88}, {0x1BC90, 0x1BC99}, {0x1BC9C, 0x1BCA3},
{0x1D000, 0x1D0F5}, {0x1D100, 0x1D126}, {0x1D129, 0x1D1E8},
{0x1D200, 0x1D245}, {0x1D300, 0x1D356}, {0x1D360, 0x1D371},
{0x1D400, 0x1D454}, {0x1D456, 0x1D49C}, {0x1D49E, 0x1D49F},
{0x1D4A2, 0x1D4A2}, {0x1D4A5, 0x1D4A6}, {0x1D4A9, 0x1D4AC},
{0x1D4AE, 0x1D4B9}, {0x1D4BB, 0x1D4BB}, {0x1D4BD, 0x1D4C3},
{0x1D4C5, 0x1D505}, {0x1D507, 0x1D50A}, {0x1D50D, 0x1D514},
{0x1D516, 0x1D51C}, {0x1D51E, 0x1D539}, {0x1D53B, 0x1D53E},
{0x1D540, 0x1D544}, {0x1D546, 0x1D546}, {0x1D54A, 0x1D550},
{0x1D552, 0x1D6A5}, {0x1D6A8, 0x1D7CB}, {0x1D7CE, 0x1DA8B},
{0x1DA9B, 0x1DA9F}, {0x1DAA1, 0x1DAAF}, {0x1E000, 0x1E006},
{0x1E008, 0x1E018}, {0x1E01B, 0x1E021}, {0x1E023, 0x1E024},
{0x1E026, 0x1E02A}, {0x1E800, 0x1E8C4}, {0x1E8C7, 0x1E8D6},
{0x1E900, 0x1E94A}, {0x1E950, 0x1E959}, {0x1E95E, 0x1E95F},
{0x1EE00, 0x1EE03}, {0x1EE05, 0x1EE1F}, {0x1EE21, 0x1EE22},
{0x1EE24, 0x1EE24}, {0x1EE27, 0x1EE27}, {0x1EE29, 0x1EE32},
{0x1EE34, 0x1EE37}, {0x1EE39, 0x1EE39}, {0x1EE3B, 0x1EE3B},
{0x1EE42, 0x1EE42}, {0x1EE47, 0x1EE47}, {0x1EE49, 0x1EE49},
{0x1EE4B, 0x1EE4B}, {0x1EE4D, 0x1EE4F}, {0x1EE51, 0x1EE52},
{0x1EE54, 0x1EE54}, {0x1EE57, 0x1EE57}, {0x1EE59, 0x1EE59},
{0x1EE5B, 0x1EE5B}, {0x1EE5D, 0x1EE5D}, {0x1EE5F, 0x1EE5F},
{0x1EE61, 0x1EE62}, {0x1EE64, 0x1EE64}, {0x1EE67, 0x1EE6A},
{0x1EE6C, 0x1EE72}, {0x1EE74, 0x1EE77}, {0x1EE79, 0x1EE7C},
{0x1EE7E, 0x1EE7E}, {0x1EE80, 0x1EE89}, {0x1EE8B, 0x1EE9B},
{0x1EEA1, 0x1EEA3}, {0x1EEA5, 0x1EEA9}, {0x1EEAB, 0x1EEBB},
{0x1EEF0, 0x1EEF1}, {0x1F000, 0x1F003}, {0x1F005, 0x1F02B},
{0x1F030, 0x1F093}, {0x1F0A0, 0x1F0AE}, {0x1F0B1, 0x1F0BF},
{0x1F0C1, 0x1F0CE}, {0x1F0D1, 0x1F0F5}, {0x1F10B, 0x1F10C},
{0x1F12E, 0x1F12E}, {0x1F16A, 0x1F16B}, {0x1F1E6, 0x1F1FF},
{0x1F321, 0x1F32C}, {0x1F336, 0x1F336}, {0x1F37D, 0x1F37D},
{0x1F394, 0x1F39F}, {0x1F3CB, 0x1F3CE}, {0x1F3D4, 0x1F3DF},
{0x1F3F1, 0x1F3F3}, {0x1F3F5, 0x1F3F7}, {0x1F43F, 0x1F43F},
{0x1F441, 0x1F441}, {0x1F4FD, 0x1F4FE}, {0x1F53E, 0x1F54A},
{0x1F54F, 0x1F54F}, {0x1F568, 0x1F579}, {0x1F57B, 0x1F594},
{0x1F597, 0x1F5A3}, {0x1F5A5, 0x1F5FA}, {0x1F650, 0x1F67F},
{0x1F6C6, 0x1F6CB}, {0x1F6CD, 0x1F6CF}, {0x1F6E0, 0x1F6EA},
{0x1F6F0, 0x1F6F3}, {0x1F700, 0x1F773}, {0x1F780, 0x1F7D4},
{0x1F800, 0x1F80B}, {0x1F810, 0x1F847}, {0x1F850, 0x1F859},
{0x1F860, 0x1F887}, {0x1F890, 0x1F8AD}, {0xE0001, 0xE0001},
{0xE0020, 0xE007F},
}
// Condition have flag EastAsianWidth whether the current locale is CJK or not.
type Condition struct {
EastAsianWidth bool

427
vendor/github.com/mattn/go-runewidth/runewidth_table.go generated vendored Normal file
View File

@ -0,0 +1,427 @@
package runewidth
var combining = table{
{0x0300, 0x036F}, {0x0483, 0x0489}, {0x07EB, 0x07F3},
{0x0C00, 0x0C00}, {0x0C04, 0x0C04}, {0x0D00, 0x0D01},
{0x135D, 0x135F}, {0x1A7F, 0x1A7F}, {0x1AB0, 0x1ABE},
{0x1B6B, 0x1B73}, {0x1DC0, 0x1DF9}, {0x1DFB, 0x1DFF},
{0x20D0, 0x20F0}, {0x2CEF, 0x2CF1}, {0x2DE0, 0x2DFF},
{0x3099, 0x309A}, {0xA66F, 0xA672}, {0xA674, 0xA67D},
{0xA69E, 0xA69F}, {0xA6F0, 0xA6F1}, {0xA8E0, 0xA8F1},
{0xFE20, 0xFE2F}, {0x101FD, 0x101FD}, {0x10376, 0x1037A},
{0x10F46, 0x10F50}, {0x11300, 0x11301}, {0x1133B, 0x1133C},
{0x11366, 0x1136C}, {0x11370, 0x11374}, {0x16AF0, 0x16AF4},
{0x1D165, 0x1D169}, {0x1D16D, 0x1D172}, {0x1D17B, 0x1D182},
{0x1D185, 0x1D18B}, {0x1D1AA, 0x1D1AD}, {0x1D242, 0x1D244},
{0x1E000, 0x1E006}, {0x1E008, 0x1E018}, {0x1E01B, 0x1E021},
{0x1E023, 0x1E024}, {0x1E026, 0x1E02A}, {0x1E8D0, 0x1E8D6},
}
var doublewidth = table{
{0x1100, 0x115F}, {0x231A, 0x231B}, {0x2329, 0x232A},
{0x23E9, 0x23EC}, {0x23F0, 0x23F0}, {0x23F3, 0x23F3},
{0x25FD, 0x25FE}, {0x2614, 0x2615}, {0x2648, 0x2653},
{0x267F, 0x267F}, {0x2693, 0x2693}, {0x26A1, 0x26A1},
{0x26AA, 0x26AB}, {0x26BD, 0x26BE}, {0x26C4, 0x26C5},
{0x26CE, 0x26CE}, {0x26D4, 0x26D4}, {0x26EA, 0x26EA},
{0x26F2, 0x26F3}, {0x26F5, 0x26F5}, {0x26FA, 0x26FA},
{0x26FD, 0x26FD}, {0x2705, 0x2705}, {0x270A, 0x270B},
{0x2728, 0x2728}, {0x274C, 0x274C}, {0x274E, 0x274E},
{0x2753, 0x2755}, {0x2757, 0x2757}, {0x2795, 0x2797},
{0x27B0, 0x27B0}, {0x27BF, 0x27BF}, {0x2B1B, 0x2B1C},
{0x2B50, 0x2B50}, {0x2B55, 0x2B55}, {0x2E80, 0x2E99},
{0x2E9B, 0x2EF3}, {0x2F00, 0x2FD5}, {0x2FF0, 0x2FFB},
{0x3000, 0x303E}, {0x3041, 0x3096}, {0x3099, 0x30FF},
{0x3105, 0x312F}, {0x3131, 0x318E}, {0x3190, 0x31BA},
{0x31C0, 0x31E3}, {0x31F0, 0x321E}, {0x3220, 0x3247},
{0x3250, 0x4DBF}, {0x4E00, 0xA48C}, {0xA490, 0xA4C6},
{0xA960, 0xA97C}, {0xAC00, 0xD7A3}, {0xF900, 0xFAFF},
{0xFE10, 0xFE19}, {0xFE30, 0xFE52}, {0xFE54, 0xFE66},
{0xFE68, 0xFE6B}, {0xFF01, 0xFF60}, {0xFFE0, 0xFFE6},
{0x16FE0, 0x16FE3}, {0x17000, 0x187F7}, {0x18800, 0x18AF2},
{0x1B000, 0x1B11E}, {0x1B150, 0x1B152}, {0x1B164, 0x1B167},
{0x1B170, 0x1B2FB}, {0x1F004, 0x1F004}, {0x1F0CF, 0x1F0CF},
{0x1F18E, 0x1F18E}, {0x1F191, 0x1F19A}, {0x1F200, 0x1F202},
{0x1F210, 0x1F23B}, {0x1F240, 0x1F248}, {0x1F250, 0x1F251},
{0x1F260, 0x1F265}, {0x1F300, 0x1F320}, {0x1F32D, 0x1F335},
{0x1F337, 0x1F37C}, {0x1F37E, 0x1F393}, {0x1F3A0, 0x1F3CA},
{0x1F3CF, 0x1F3D3}, {0x1F3E0, 0x1F3F0}, {0x1F3F4, 0x1F3F4},
{0x1F3F8, 0x1F43E}, {0x1F440, 0x1F440}, {0x1F442, 0x1F4FC},
{0x1F4FF, 0x1F53D}, {0x1F54B, 0x1F54E}, {0x1F550, 0x1F567},
{0x1F57A, 0x1F57A}, {0x1F595, 0x1F596}, {0x1F5A4, 0x1F5A4},
{0x1F5FB, 0x1F64F}, {0x1F680, 0x1F6C5}, {0x1F6CC, 0x1F6CC},
{0x1F6D0, 0x1F6D2}, {0x1F6D5, 0x1F6D5}, {0x1F6EB, 0x1F6EC},
{0x1F6F4, 0x1F6FA}, {0x1F7E0, 0x1F7EB}, {0x1F90D, 0x1F971},
{0x1F973, 0x1F976}, {0x1F97A, 0x1F9A2}, {0x1F9A5, 0x1F9AA},
{0x1F9AE, 0x1F9CA}, {0x1F9CD, 0x1F9FF}, {0x1FA70, 0x1FA73},
{0x1FA78, 0x1FA7A}, {0x1FA80, 0x1FA82}, {0x1FA90, 0x1FA95},
{0x20000, 0x2FFFD}, {0x30000, 0x3FFFD},
}
var ambiguous = table{
{0x00A1, 0x00A1}, {0x00A4, 0x00A4}, {0x00A7, 0x00A8},
{0x00AA, 0x00AA}, {0x00AD, 0x00AE}, {0x00B0, 0x00B4},
{0x00B6, 0x00BA}, {0x00BC, 0x00BF}, {0x00C6, 0x00C6},
{0x00D0, 0x00D0}, {0x00D7, 0x00D8}, {0x00DE, 0x00E1},
{0x00E6, 0x00E6}, {0x00E8, 0x00EA}, {0x00EC, 0x00ED},
{0x00F0, 0x00F0}, {0x00F2, 0x00F3}, {0x00F7, 0x00FA},
{0x00FC, 0x00FC}, {0x00FE, 0x00FE}, {0x0101, 0x0101},
{0x0111, 0x0111}, {0x0113, 0x0113}, {0x011B, 0x011B},
{0x0126, 0x0127}, {0x012B, 0x012B}, {0x0131, 0x0133},
{0x0138, 0x0138}, {0x013F, 0x0142}, {0x0144, 0x0144},
{0x0148, 0x014B}, {0x014D, 0x014D}, {0x0152, 0x0153},
{0x0166, 0x0167}, {0x016B, 0x016B}, {0x01CE, 0x01CE},
{0x01D0, 0x01D0}, {0x01D2, 0x01D2}, {0x01D4, 0x01D4},
{0x01D6, 0x01D6}, {0x01D8, 0x01D8}, {0x01DA, 0x01DA},
{0x01DC, 0x01DC}, {0x0251, 0x0251}, {0x0261, 0x0261},
{0x02C4, 0x02C4}, {0x02C7, 0x02C7}, {0x02C9, 0x02CB},
{0x02CD, 0x02CD}, {0x02D0, 0x02D0}, {0x02D8, 0x02DB},
{0x02DD, 0x02DD}, {0x02DF, 0x02DF}, {0x0300, 0x036F},
{0x0391, 0x03A1}, {0x03A3, 0x03A9}, {0x03B1, 0x03C1},
{0x03C3, 0x03C9}, {0x0401, 0x0401}, {0x0410, 0x044F},
{0x0451, 0x0451}, {0x2010, 0x2010}, {0x2013, 0x2016},
{0x2018, 0x2019}, {0x201C, 0x201D}, {0x2020, 0x2022},
{0x2024, 0x2027}, {0x2030, 0x2030}, {0x2032, 0x2033},
{0x2035, 0x2035}, {0x203B, 0x203B}, {0x203E, 0x203E},
{0x2074, 0x2074}, {0x207F, 0x207F}, {0x2081, 0x2084},
{0x20AC, 0x20AC}, {0x2103, 0x2103}, {0x2105, 0x2105},
{0x2109, 0x2109}, {0x2113, 0x2113}, {0x2116, 0x2116},
{0x2121, 0x2122}, {0x2126, 0x2126}, {0x212B, 0x212B},
{0x2153, 0x2154}, {0x215B, 0x215E}, {0x2160, 0x216B},
{0x2170, 0x2179}, {0x2189, 0x2189}, {0x2190, 0x2199},
{0x21B8, 0x21B9}, {0x21D2, 0x21D2}, {0x21D4, 0x21D4},
{0x21E7, 0x21E7}, {0x2200, 0x2200}, {0x2202, 0x2203},
{0x2207, 0x2208}, {0x220B, 0x220B}, {0x220F, 0x220F},
{0x2211, 0x2211}, {0x2215, 0x2215}, {0x221A, 0x221A},
{0x221D, 0x2220}, {0x2223, 0x2223}, {0x2225, 0x2225},
{0x2227, 0x222C}, {0x222E, 0x222E}, {0x2234, 0x2237},
{0x223C, 0x223D}, {0x2248, 0x2248}, {0x224C, 0x224C},
{0x2252, 0x2252}, {0x2260, 0x2261}, {0x2264, 0x2267},
{0x226A, 0x226B}, {0x226E, 0x226F}, {0x2282, 0x2283},
{0x2286, 0x2287}, {0x2295, 0x2295}, {0x2299, 0x2299},
{0x22A5, 0x22A5}, {0x22BF, 0x22BF}, {0x2312, 0x2312},
{0x2460, 0x24E9}, {0x24EB, 0x254B}, {0x2550, 0x2573},
{0x2580, 0x258F}, {0x2592, 0x2595}, {0x25A0, 0x25A1},
{0x25A3, 0x25A9}, {0x25B2, 0x25B3}, {0x25B6, 0x25B7},
{0x25BC, 0x25BD}, {0x25C0, 0x25C1}, {0x25C6, 0x25C8},
{0x25CB, 0x25CB}, {0x25CE, 0x25D1}, {0x25E2, 0x25E5},
{0x25EF, 0x25EF}, {0x2605, 0x2606}, {0x2609, 0x2609},
{0x260E, 0x260F}, {0x261C, 0x261C}, {0x261E, 0x261E},
{0x2640, 0x2640}, {0x2642, 0x2642}, {0x2660, 0x2661},
{0x2663, 0x2665}, {0x2667, 0x266A}, {0x266C, 0x266D},
{0x266F, 0x266F}, {0x269E, 0x269F}, {0x26BF, 0x26BF},
{0x26C6, 0x26CD}, {0x26CF, 0x26D3}, {0x26D5, 0x26E1},
{0x26E3, 0x26E3}, {0x26E8, 0x26E9}, {0x26EB, 0x26F1},
{0x26F4, 0x26F4}, {0x26F6, 0x26F9}, {0x26FB, 0x26FC},
{0x26FE, 0x26FF}, {0x273D, 0x273D}, {0x2776, 0x277F},
{0x2B56, 0x2B59}, {0x3248, 0x324F}, {0xE000, 0xF8FF},
{0xFE00, 0xFE0F}, {0xFFFD, 0xFFFD}, {0x1F100, 0x1F10A},
{0x1F110, 0x1F12D}, {0x1F130, 0x1F169}, {0x1F170, 0x1F18D},
{0x1F18F, 0x1F190}, {0x1F19B, 0x1F1AC}, {0xE0100, 0xE01EF},
{0xF0000, 0xFFFFD}, {0x100000, 0x10FFFD},
}
var notassigned = table{
{0x27E6, 0x27ED}, {0x2985, 0x2986},
}
var neutral = table{
{0x0000, 0x001F}, {0x007F, 0x00A0}, {0x00A9, 0x00A9},
{0x00AB, 0x00AB}, {0x00B5, 0x00B5}, {0x00BB, 0x00BB},
{0x00C0, 0x00C5}, {0x00C7, 0x00CF}, {0x00D1, 0x00D6},
{0x00D9, 0x00DD}, {0x00E2, 0x00E5}, {0x00E7, 0x00E7},
{0x00EB, 0x00EB}, {0x00EE, 0x00EF}, {0x00F1, 0x00F1},
{0x00F4, 0x00F6}, {0x00FB, 0x00FB}, {0x00FD, 0x00FD},
{0x00FF, 0x0100}, {0x0102, 0x0110}, {0x0112, 0x0112},
{0x0114, 0x011A}, {0x011C, 0x0125}, {0x0128, 0x012A},
{0x012C, 0x0130}, {0x0134, 0x0137}, {0x0139, 0x013E},
{0x0143, 0x0143}, {0x0145, 0x0147}, {0x014C, 0x014C},
{0x014E, 0x0151}, {0x0154, 0x0165}, {0x0168, 0x016A},
{0x016C, 0x01CD}, {0x01CF, 0x01CF}, {0x01D1, 0x01D1},
{0x01D3, 0x01D3}, {0x01D5, 0x01D5}, {0x01D7, 0x01D7},
{0x01D9, 0x01D9}, {0x01DB, 0x01DB}, {0x01DD, 0x0250},
{0x0252, 0x0260}, {0x0262, 0x02C3}, {0x02C5, 0x02C6},
{0x02C8, 0x02C8}, {0x02CC, 0x02CC}, {0x02CE, 0x02CF},
{0x02D1, 0x02D7}, {0x02DC, 0x02DC}, {0x02DE, 0x02DE},
{0x02E0, 0x02FF}, {0x0370, 0x0377}, {0x037A, 0x037F},
{0x0384, 0x038A}, {0x038C, 0x038C}, {0x038E, 0x0390},
{0x03AA, 0x03B0}, {0x03C2, 0x03C2}, {0x03CA, 0x0400},
{0x0402, 0x040F}, {0x0450, 0x0450}, {0x0452, 0x052F},
{0x0531, 0x0556}, {0x0559, 0x058A}, {0x058D, 0x058F},
{0x0591, 0x05C7}, {0x05D0, 0x05EA}, {0x05EF, 0x05F4},
{0x0600, 0x061C}, {0x061E, 0x070D}, {0x070F, 0x074A},
{0x074D, 0x07B1}, {0x07C0, 0x07FA}, {0x07FD, 0x082D},
{0x0830, 0x083E}, {0x0840, 0x085B}, {0x085E, 0x085E},
{0x0860, 0x086A}, {0x08A0, 0x08B4}, {0x08B6, 0x08BD},
{0x08D3, 0x0983}, {0x0985, 0x098C}, {0x098F, 0x0990},
{0x0993, 0x09A8}, {0x09AA, 0x09B0}, {0x09B2, 0x09B2},
{0x09B6, 0x09B9}, {0x09BC, 0x09C4}, {0x09C7, 0x09C8},
{0x09CB, 0x09CE}, {0x09D7, 0x09D7}, {0x09DC, 0x09DD},
{0x09DF, 0x09E3}, {0x09E6, 0x09FE}, {0x0A01, 0x0A03},
{0x0A05, 0x0A0A}, {0x0A0F, 0x0A10}, {0x0A13, 0x0A28},
{0x0A2A, 0x0A30}, {0x0A32, 0x0A33}, {0x0A35, 0x0A36},
{0x0A38, 0x0A39}, {0x0A3C, 0x0A3C}, {0x0A3E, 0x0A42},
{0x0A47, 0x0A48}, {0x0A4B, 0x0A4D}, {0x0A51, 0x0A51},
{0x0A59, 0x0A5C}, {0x0A5E, 0x0A5E}, {0x0A66, 0x0A76},
{0x0A81, 0x0A83}, {0x0A85, 0x0A8D}, {0x0A8F, 0x0A91},
{0x0A93, 0x0AA8}, {0x0AAA, 0x0AB0}, {0x0AB2, 0x0AB3},
{0x0AB5, 0x0AB9}, {0x0ABC, 0x0AC5}, {0x0AC7, 0x0AC9},
{0x0ACB, 0x0ACD}, {0x0AD0, 0x0AD0}, {0x0AE0, 0x0AE3},
{0x0AE6, 0x0AF1}, {0x0AF9, 0x0AFF}, {0x0B01, 0x0B03},
{0x0B05, 0x0B0C}, {0x0B0F, 0x0B10}, {0x0B13, 0x0B28},
{0x0B2A, 0x0B30}, {0x0B32, 0x0B33}, {0x0B35, 0x0B39},
{0x0B3C, 0x0B44}, {0x0B47, 0x0B48}, {0x0B4B, 0x0B4D},
{0x0B56, 0x0B57}, {0x0B5C, 0x0B5D}, {0x0B5F, 0x0B63},
{0x0B66, 0x0B77}, {0x0B82, 0x0B83}, {0x0B85, 0x0B8A},
{0x0B8E, 0x0B90}, {0x0B92, 0x0B95}, {0x0B99, 0x0B9A},
{0x0B9C, 0x0B9C}, {0x0B9E, 0x0B9F}, {0x0BA3, 0x0BA4},
{0x0BA8, 0x0BAA}, {0x0BAE, 0x0BB9}, {0x0BBE, 0x0BC2},
{0x0BC6, 0x0BC8}, {0x0BCA, 0x0BCD}, {0x0BD0, 0x0BD0},
{0x0BD7, 0x0BD7}, {0x0BE6, 0x0BFA}, {0x0C00, 0x0C0C},
{0x0C0E, 0x0C10}, {0x0C12, 0x0C28}, {0x0C2A, 0x0C39},
{0x0C3D, 0x0C44}, {0x0C46, 0x0C48}, {0x0C4A, 0x0C4D},
{0x0C55, 0x0C56}, {0x0C58, 0x0C5A}, {0x0C60, 0x0C63},
{0x0C66, 0x0C6F}, {0x0C77, 0x0C8C}, {0x0C8E, 0x0C90},
{0x0C92, 0x0CA8}, {0x0CAA, 0x0CB3}, {0x0CB5, 0x0CB9},
{0x0CBC, 0x0CC4}, {0x0CC6, 0x0CC8}, {0x0CCA, 0x0CCD},
{0x0CD5, 0x0CD6}, {0x0CDE, 0x0CDE}, {0x0CE0, 0x0CE3},
{0x0CE6, 0x0CEF}, {0x0CF1, 0x0CF2}, {0x0D00, 0x0D03},
{0x0D05, 0x0D0C}, {0x0D0E, 0x0D10}, {0x0D12, 0x0D44},
{0x0D46, 0x0D48}, {0x0D4A, 0x0D4F}, {0x0D54, 0x0D63},
{0x0D66, 0x0D7F}, {0x0D82, 0x0D83}, {0x0D85, 0x0D96},
{0x0D9A, 0x0DB1}, {0x0DB3, 0x0DBB}, {0x0DBD, 0x0DBD},
{0x0DC0, 0x0DC6}, {0x0DCA, 0x0DCA}, {0x0DCF, 0x0DD4},
{0x0DD6, 0x0DD6}, {0x0DD8, 0x0DDF}, {0x0DE6, 0x0DEF},
{0x0DF2, 0x0DF4}, {0x0E01, 0x0E3A}, {0x0E3F, 0x0E5B},
{0x0E81, 0x0E82}, {0x0E84, 0x0E84}, {0x0E86, 0x0E8A},
{0x0E8C, 0x0EA3}, {0x0EA5, 0x0EA5}, {0x0EA7, 0x0EBD},
{0x0EC0, 0x0EC4}, {0x0EC6, 0x0EC6}, {0x0EC8, 0x0ECD},
{0x0ED0, 0x0ED9}, {0x0EDC, 0x0EDF}, {0x0F00, 0x0F47},
{0x0F49, 0x0F6C}, {0x0F71, 0x0F97}, {0x0F99, 0x0FBC},
{0x0FBE, 0x0FCC}, {0x0FCE, 0x0FDA}, {0x1000, 0x10C5},
{0x10C7, 0x10C7}, {0x10CD, 0x10CD}, {0x10D0, 0x10FF},
{0x1160, 0x1248}, {0x124A, 0x124D}, {0x1250, 0x1256},
{0x1258, 0x1258}, {0x125A, 0x125D}, {0x1260, 0x1288},
{0x128A, 0x128D}, {0x1290, 0x12B0}, {0x12B2, 0x12B5},
{0x12B8, 0x12BE}, {0x12C0, 0x12C0}, {0x12C2, 0x12C5},
{0x12C8, 0x12D6}, {0x12D8, 0x1310}, {0x1312, 0x1315},
{0x1318, 0x135A}, {0x135D, 0x137C}, {0x1380, 0x1399},
{0x13A0, 0x13F5}, {0x13F8, 0x13FD}, {0x1400, 0x169C},
{0x16A0, 0x16F8}, {0x1700, 0x170C}, {0x170E, 0x1714},
{0x1720, 0x1736}, {0x1740, 0x1753}, {0x1760, 0x176C},
{0x176E, 0x1770}, {0x1772, 0x1773}, {0x1780, 0x17DD},
{0x17E0, 0x17E9}, {0x17F0, 0x17F9}, {0x1800, 0x180E},
{0x1810, 0x1819}, {0x1820, 0x1878}, {0x1880, 0x18AA},
{0x18B0, 0x18F5}, {0x1900, 0x191E}, {0x1920, 0x192B},
{0x1930, 0x193B}, {0x1940, 0x1940}, {0x1944, 0x196D},
{0x1970, 0x1974}, {0x1980, 0x19AB}, {0x19B0, 0x19C9},
{0x19D0, 0x19DA}, {0x19DE, 0x1A1B}, {0x1A1E, 0x1A5E},
{0x1A60, 0x1A7C}, {0x1A7F, 0x1A89}, {0x1A90, 0x1A99},
{0x1AA0, 0x1AAD}, {0x1AB0, 0x1ABE}, {0x1B00, 0x1B4B},
{0x1B50, 0x1B7C}, {0x1B80, 0x1BF3}, {0x1BFC, 0x1C37},
{0x1C3B, 0x1C49}, {0x1C4D, 0x1C88}, {0x1C90, 0x1CBA},
{0x1CBD, 0x1CC7}, {0x1CD0, 0x1CFA}, {0x1D00, 0x1DF9},
{0x1DFB, 0x1F15}, {0x1F18, 0x1F1D}, {0x1F20, 0x1F45},
{0x1F48, 0x1F4D}, {0x1F50, 0x1F57}, {0x1F59, 0x1F59},
{0x1F5B, 0x1F5B}, {0x1F5D, 0x1F5D}, {0x1F5F, 0x1F7D},
{0x1F80, 0x1FB4}, {0x1FB6, 0x1FC4}, {0x1FC6, 0x1FD3},
{0x1FD6, 0x1FDB}, {0x1FDD, 0x1FEF}, {0x1FF2, 0x1FF4},
{0x1FF6, 0x1FFE}, {0x2000, 0x200F}, {0x2011, 0x2012},
{0x2017, 0x2017}, {0x201A, 0x201B}, {0x201E, 0x201F},
{0x2023, 0x2023}, {0x2028, 0x202F}, {0x2031, 0x2031},
{0x2034, 0x2034}, {0x2036, 0x203A}, {0x203C, 0x203D},
{0x203F, 0x2064}, {0x2066, 0x2071}, {0x2075, 0x207E},
{0x2080, 0x2080}, {0x2085, 0x208E}, {0x2090, 0x209C},
{0x20A0, 0x20A8}, {0x20AA, 0x20AB}, {0x20AD, 0x20BF},
{0x20D0, 0x20F0}, {0x2100, 0x2102}, {0x2104, 0x2104},
{0x2106, 0x2108}, {0x210A, 0x2112}, {0x2114, 0x2115},
{0x2117, 0x2120}, {0x2123, 0x2125}, {0x2127, 0x212A},
{0x212C, 0x2152}, {0x2155, 0x215A}, {0x215F, 0x215F},
{0x216C, 0x216F}, {0x217A, 0x2188}, {0x218A, 0x218B},
{0x219A, 0x21B7}, {0x21BA, 0x21D1}, {0x21D3, 0x21D3},
{0x21D5, 0x21E6}, {0x21E8, 0x21FF}, {0x2201, 0x2201},
{0x2204, 0x2206}, {0x2209, 0x220A}, {0x220C, 0x220E},
{0x2210, 0x2210}, {0x2212, 0x2214}, {0x2216, 0x2219},
{0x221B, 0x221C}, {0x2221, 0x2222}, {0x2224, 0x2224},
{0x2226, 0x2226}, {0x222D, 0x222D}, {0x222F, 0x2233},
{0x2238, 0x223B}, {0x223E, 0x2247}, {0x2249, 0x224B},
{0x224D, 0x2251}, {0x2253, 0x225F}, {0x2262, 0x2263},
{0x2268, 0x2269}, {0x226C, 0x226D}, {0x2270, 0x2281},
{0x2284, 0x2285}, {0x2288, 0x2294}, {0x2296, 0x2298},
{0x229A, 0x22A4}, {0x22A6, 0x22BE}, {0x22C0, 0x2311},
{0x2313, 0x2319}, {0x231C, 0x2328}, {0x232B, 0x23E8},
{0x23ED, 0x23EF}, {0x23F1, 0x23F2}, {0x23F4, 0x2426},
{0x2440, 0x244A}, {0x24EA, 0x24EA}, {0x254C, 0x254F},
{0x2574, 0x257F}, {0x2590, 0x2591}, {0x2596, 0x259F},
{0x25A2, 0x25A2}, {0x25AA, 0x25B1}, {0x25B4, 0x25B5},
{0x25B8, 0x25BB}, {0x25BE, 0x25BF}, {0x25C2, 0x25C5},
{0x25C9, 0x25CA}, {0x25CC, 0x25CD}, {0x25D2, 0x25E1},
{0x25E6, 0x25EE}, {0x25F0, 0x25FC}, {0x25FF, 0x2604},
{0x2607, 0x2608}, {0x260A, 0x260D}, {0x2610, 0x2613},
{0x2616, 0x261B}, {0x261D, 0x261D}, {0x261F, 0x263F},
{0x2641, 0x2641}, {0x2643, 0x2647}, {0x2654, 0x265F},
{0x2662, 0x2662}, {0x2666, 0x2666}, {0x266B, 0x266B},
{0x266E, 0x266E}, {0x2670, 0x267E}, {0x2680, 0x2692},
{0x2694, 0x269D}, {0x26A0, 0x26A0}, {0x26A2, 0x26A9},
{0x26AC, 0x26BC}, {0x26C0, 0x26C3}, {0x26E2, 0x26E2},
{0x26E4, 0x26E7}, {0x2700, 0x2704}, {0x2706, 0x2709},
{0x270C, 0x2727}, {0x2729, 0x273C}, {0x273E, 0x274B},
{0x274D, 0x274D}, {0x274F, 0x2752}, {0x2756, 0x2756},
{0x2758, 0x2775}, {0x2780, 0x2794}, {0x2798, 0x27AF},
{0x27B1, 0x27BE}, {0x27C0, 0x27E5}, {0x27EE, 0x2984},
{0x2987, 0x2B1A}, {0x2B1D, 0x2B4F}, {0x2B51, 0x2B54},
{0x2B5A, 0x2B73}, {0x2B76, 0x2B95}, {0x2B98, 0x2C2E},
{0x2C30, 0x2C5E}, {0x2C60, 0x2CF3}, {0x2CF9, 0x2D25},
{0x2D27, 0x2D27}, {0x2D2D, 0x2D2D}, {0x2D30, 0x2D67},
{0x2D6F, 0x2D70}, {0x2D7F, 0x2D96}, {0x2DA0, 0x2DA6},
{0x2DA8, 0x2DAE}, {0x2DB0, 0x2DB6}, {0x2DB8, 0x2DBE},
{0x2DC0, 0x2DC6}, {0x2DC8, 0x2DCE}, {0x2DD0, 0x2DD6},
{0x2DD8, 0x2DDE}, {0x2DE0, 0x2E4F}, {0x303F, 0x303F},
{0x4DC0, 0x4DFF}, {0xA4D0, 0xA62B}, {0xA640, 0xA6F7},
{0xA700, 0xA7BF}, {0xA7C2, 0xA7C6}, {0xA7F7, 0xA82B},
{0xA830, 0xA839}, {0xA840, 0xA877}, {0xA880, 0xA8C5},
{0xA8CE, 0xA8D9}, {0xA8E0, 0xA953}, {0xA95F, 0xA95F},
{0xA980, 0xA9CD}, {0xA9CF, 0xA9D9}, {0xA9DE, 0xA9FE},
{0xAA00, 0xAA36}, {0xAA40, 0xAA4D}, {0xAA50, 0xAA59},
{0xAA5C, 0xAAC2}, {0xAADB, 0xAAF6}, {0xAB01, 0xAB06},
{0xAB09, 0xAB0E}, {0xAB11, 0xAB16}, {0xAB20, 0xAB26},
{0xAB28, 0xAB2E}, {0xAB30, 0xAB67}, {0xAB70, 0xABED},
{0xABF0, 0xABF9}, {0xD7B0, 0xD7C6}, {0xD7CB, 0xD7FB},
{0xD800, 0xDFFF}, {0xFB00, 0xFB06}, {0xFB13, 0xFB17},
{0xFB1D, 0xFB36}, {0xFB38, 0xFB3C}, {0xFB3E, 0xFB3E},
{0xFB40, 0xFB41}, {0xFB43, 0xFB44}, {0xFB46, 0xFBC1},
{0xFBD3, 0xFD3F}, {0xFD50, 0xFD8F}, {0xFD92, 0xFDC7},
{0xFDF0, 0xFDFD}, {0xFE20, 0xFE2F}, {0xFE70, 0xFE74},
{0xFE76, 0xFEFC}, {0xFEFF, 0xFEFF}, {0xFFF9, 0xFFFC},
{0x10000, 0x1000B}, {0x1000D, 0x10026}, {0x10028, 0x1003A},
{0x1003C, 0x1003D}, {0x1003F, 0x1004D}, {0x10050, 0x1005D},
{0x10080, 0x100FA}, {0x10100, 0x10102}, {0x10107, 0x10133},
{0x10137, 0x1018E}, {0x10190, 0x1019B}, {0x101A0, 0x101A0},
{0x101D0, 0x101FD}, {0x10280, 0x1029C}, {0x102A0, 0x102D0},
{0x102E0, 0x102FB}, {0x10300, 0x10323}, {0x1032D, 0x1034A},
{0x10350, 0x1037A}, {0x10380, 0x1039D}, {0x1039F, 0x103C3},
{0x103C8, 0x103D5}, {0x10400, 0x1049D}, {0x104A0, 0x104A9},
{0x104B0, 0x104D3}, {0x104D8, 0x104FB}, {0x10500, 0x10527},
{0x10530, 0x10563}, {0x1056F, 0x1056F}, {0x10600, 0x10736},
{0x10740, 0x10755}, {0x10760, 0x10767}, {0x10800, 0x10805},
{0x10808, 0x10808}, {0x1080A, 0x10835}, {0x10837, 0x10838},
{0x1083C, 0x1083C}, {0x1083F, 0x10855}, {0x10857, 0x1089E},
{0x108A7, 0x108AF}, {0x108E0, 0x108F2}, {0x108F4, 0x108F5},
{0x108FB, 0x1091B}, {0x1091F, 0x10939}, {0x1093F, 0x1093F},
{0x10980, 0x109B7}, {0x109BC, 0x109CF}, {0x109D2, 0x10A03},
{0x10A05, 0x10A06}, {0x10A0C, 0x10A13}, {0x10A15, 0x10A17},
{0x10A19, 0x10A35}, {0x10A38, 0x10A3A}, {0x10A3F, 0x10A48},
{0x10A50, 0x10A58}, {0x10A60, 0x10A9F}, {0x10AC0, 0x10AE6},
{0x10AEB, 0x10AF6}, {0x10B00, 0x10B35}, {0x10B39, 0x10B55},
{0x10B58, 0x10B72}, {0x10B78, 0x10B91}, {0x10B99, 0x10B9C},
{0x10BA9, 0x10BAF}, {0x10C00, 0x10C48}, {0x10C80, 0x10CB2},
{0x10CC0, 0x10CF2}, {0x10CFA, 0x10D27}, {0x10D30, 0x10D39},
{0x10E60, 0x10E7E}, {0x10F00, 0x10F27}, {0x10F30, 0x10F59},
{0x10FE0, 0x10FF6}, {0x11000, 0x1104D}, {0x11052, 0x1106F},
{0x1107F, 0x110C1}, {0x110CD, 0x110CD}, {0x110D0, 0x110E8},
{0x110F0, 0x110F9}, {0x11100, 0x11134}, {0x11136, 0x11146},
{0x11150, 0x11176}, {0x11180, 0x111CD}, {0x111D0, 0x111DF},
{0x111E1, 0x111F4}, {0x11200, 0x11211}, {0x11213, 0x1123E},
{0x11280, 0x11286}, {0x11288, 0x11288}, {0x1128A, 0x1128D},
{0x1128F, 0x1129D}, {0x1129F, 0x112A9}, {0x112B0, 0x112EA},
{0x112F0, 0x112F9}, {0x11300, 0x11303}, {0x11305, 0x1130C},
{0x1130F, 0x11310}, {0x11313, 0x11328}, {0x1132A, 0x11330},
{0x11332, 0x11333}, {0x11335, 0x11339}, {0x1133B, 0x11344},
{0x11347, 0x11348}, {0x1134B, 0x1134D}, {0x11350, 0x11350},
{0x11357, 0x11357}, {0x1135D, 0x11363}, {0x11366, 0x1136C},
{0x11370, 0x11374}, {0x11400, 0x11459}, {0x1145B, 0x1145B},
{0x1145D, 0x1145F}, {0x11480, 0x114C7}, {0x114D0, 0x114D9},
{0x11580, 0x115B5}, {0x115B8, 0x115DD}, {0x11600, 0x11644},
{0x11650, 0x11659}, {0x11660, 0x1166C}, {0x11680, 0x116B8},
{0x116C0, 0x116C9}, {0x11700, 0x1171A}, {0x1171D, 0x1172B},
{0x11730, 0x1173F}, {0x11800, 0x1183B}, {0x118A0, 0x118F2},
{0x118FF, 0x118FF}, {0x119A0, 0x119A7}, {0x119AA, 0x119D7},
{0x119DA, 0x119E4}, {0x11A00, 0x11A47}, {0x11A50, 0x11AA2},
{0x11AC0, 0x11AF8}, {0x11C00, 0x11C08}, {0x11C0A, 0x11C36},
{0x11C38, 0x11C45}, {0x11C50, 0x11C6C}, {0x11C70, 0x11C8F},
{0x11C92, 0x11CA7}, {0x11CA9, 0x11CB6}, {0x11D00, 0x11D06},
{0x11D08, 0x11D09}, {0x11D0B, 0x11D36}, {0x11D3A, 0x11D3A},
{0x11D3C, 0x11D3D}, {0x11D3F, 0x11D47}, {0x11D50, 0x11D59},
{0x11D60, 0x11D65}, {0x11D67, 0x11D68}, {0x11D6A, 0x11D8E},
{0x11D90, 0x11D91}, {0x11D93, 0x11D98}, {0x11DA0, 0x11DA9},
{0x11EE0, 0x11EF8}, {0x11FC0, 0x11FF1}, {0x11FFF, 0x12399},
{0x12400, 0x1246E}, {0x12470, 0x12474}, {0x12480, 0x12543},
{0x13000, 0x1342E}, {0x13430, 0x13438}, {0x14400, 0x14646},
{0x16800, 0x16A38}, {0x16A40, 0x16A5E}, {0x16A60, 0x16A69},
{0x16A6E, 0x16A6F}, {0x16AD0, 0x16AED}, {0x16AF0, 0x16AF5},
{0x16B00, 0x16B45}, {0x16B50, 0x16B59}, {0x16B5B, 0x16B61},
{0x16B63, 0x16B77}, {0x16B7D, 0x16B8F}, {0x16E40, 0x16E9A},
{0x16F00, 0x16F4A}, {0x16F4F, 0x16F87}, {0x16F8F, 0x16F9F},
{0x1BC00, 0x1BC6A}, {0x1BC70, 0x1BC7C}, {0x1BC80, 0x1BC88},
{0x1BC90, 0x1BC99}, {0x1BC9C, 0x1BCA3}, {0x1D000, 0x1D0F5},
{0x1D100, 0x1D126}, {0x1D129, 0x1D1E8}, {0x1D200, 0x1D245},
{0x1D2E0, 0x1D2F3}, {0x1D300, 0x1D356}, {0x1D360, 0x1D378},
{0x1D400, 0x1D454}, {0x1D456, 0x1D49C}, {0x1D49E, 0x1D49F},
{0x1D4A2, 0x1D4A2}, {0x1D4A5, 0x1D4A6}, {0x1D4A9, 0x1D4AC},
{0x1D4AE, 0x1D4B9}, {0x1D4BB, 0x1D4BB}, {0x1D4BD, 0x1D4C3},
{0x1D4C5, 0x1D505}, {0x1D507, 0x1D50A}, {0x1D50D, 0x1D514},
{0x1D516, 0x1D51C}, {0x1D51E, 0x1D539}, {0x1D53B, 0x1D53E},
{0x1D540, 0x1D544}, {0x1D546, 0x1D546}, {0x1D54A, 0x1D550},
{0x1D552, 0x1D6A5}, {0x1D6A8, 0x1D7CB}, {0x1D7CE, 0x1DA8B},
{0x1DA9B, 0x1DA9F}, {0x1DAA1, 0x1DAAF}, {0x1E000, 0x1E006},
{0x1E008, 0x1E018}, {0x1E01B, 0x1E021}, {0x1E023, 0x1E024},
{0x1E026, 0x1E02A}, {0x1E100, 0x1E12C}, {0x1E130, 0x1E13D},
{0x1E140, 0x1E149}, {0x1E14E, 0x1E14F}, {0x1E2C0, 0x1E2F9},
{0x1E2FF, 0x1E2FF}, {0x1E800, 0x1E8C4}, {0x1E8C7, 0x1E8D6},
{0x1E900, 0x1E94B}, {0x1E950, 0x1E959}, {0x1E95E, 0x1E95F},
{0x1EC71, 0x1ECB4}, {0x1ED01, 0x1ED3D}, {0x1EE00, 0x1EE03},
{0x1EE05, 0x1EE1F}, {0x1EE21, 0x1EE22}, {0x1EE24, 0x1EE24},
{0x1EE27, 0x1EE27}, {0x1EE29, 0x1EE32}, {0x1EE34, 0x1EE37},
{0x1EE39, 0x1EE39}, {0x1EE3B, 0x1EE3B}, {0x1EE42, 0x1EE42},
{0x1EE47, 0x1EE47}, {0x1EE49, 0x1EE49}, {0x1EE4B, 0x1EE4B},
{0x1EE4D, 0x1EE4F}, {0x1EE51, 0x1EE52}, {0x1EE54, 0x1EE54},
{0x1EE57, 0x1EE57}, {0x1EE59, 0x1EE59}, {0x1EE5B, 0x1EE5B},
{0x1EE5D, 0x1EE5D}, {0x1EE5F, 0x1EE5F}, {0x1EE61, 0x1EE62},
{0x1EE64, 0x1EE64}, {0x1EE67, 0x1EE6A}, {0x1EE6C, 0x1EE72},
{0x1EE74, 0x1EE77}, {0x1EE79, 0x1EE7C}, {0x1EE7E, 0x1EE7E},
{0x1EE80, 0x1EE89}, {0x1EE8B, 0x1EE9B}, {0x1EEA1, 0x1EEA3},
{0x1EEA5, 0x1EEA9}, {0x1EEAB, 0x1EEBB}, {0x1EEF0, 0x1EEF1},
{0x1F000, 0x1F003}, {0x1F005, 0x1F02B}, {0x1F030, 0x1F093},
{0x1F0A0, 0x1F0AE}, {0x1F0B1, 0x1F0BF}, {0x1F0C1, 0x1F0CE},
{0x1F0D1, 0x1F0F5}, {0x1F10B, 0x1F10C}, {0x1F12E, 0x1F12F},
{0x1F16A, 0x1F16C}, {0x1F1E6, 0x1F1FF}, {0x1F321, 0x1F32C},
{0x1F336, 0x1F336}, {0x1F37D, 0x1F37D}, {0x1F394, 0x1F39F},
{0x1F3CB, 0x1F3CE}, {0x1F3D4, 0x1F3DF}, {0x1F3F1, 0x1F3F3},
{0x1F3F5, 0x1F3F7}, {0x1F43F, 0x1F43F}, {0x1F441, 0x1F441},
{0x1F4FD, 0x1F4FE}, {0x1F53E, 0x1F54A}, {0x1F54F, 0x1F54F},
{0x1F568, 0x1F579}, {0x1F57B, 0x1F594}, {0x1F597, 0x1F5A3},
{0x1F5A5, 0x1F5FA}, {0x1F650, 0x1F67F}, {0x1F6C6, 0x1F6CB},
{0x1F6CD, 0x1F6CF}, {0x1F6D3, 0x1F6D4}, {0x1F6E0, 0x1F6EA},
{0x1F6F0, 0x1F6F3}, {0x1F700, 0x1F773}, {0x1F780, 0x1F7D8},
{0x1F800, 0x1F80B}, {0x1F810, 0x1F847}, {0x1F850, 0x1F859},
{0x1F860, 0x1F887}, {0x1F890, 0x1F8AD}, {0x1F900, 0x1F90B},
{0x1FA00, 0x1FA53}, {0x1FA60, 0x1FA6D}, {0xE0001, 0xE0001},
{0xE0020, 0xE007F},
}
var emoji = table{
{0x203C, 0x203C}, {0x2049, 0x2049}, {0x2122, 0x2122},
{0x2139, 0x2139}, {0x2194, 0x2199}, {0x21A9, 0x21AA},
{0x231A, 0x231B}, {0x2328, 0x2328}, {0x2388, 0x2388},
{0x23CF, 0x23CF}, {0x23E9, 0x23F3}, {0x23F8, 0x23FA},
{0x24C2, 0x24C2}, {0x25AA, 0x25AB}, {0x25B6, 0x25B6},
{0x25C0, 0x25C0}, {0x25FB, 0x25FE}, {0x2600, 0x2605},
{0x2607, 0x2612}, {0x2614, 0x2685}, {0x2690, 0x2705},
{0x2708, 0x2712}, {0x2714, 0x2714}, {0x2716, 0x2716},
{0x271D, 0x271D}, {0x2721, 0x2721}, {0x2728, 0x2728},
{0x2733, 0x2734}, {0x2744, 0x2744}, {0x2747, 0x2747},
{0x274C, 0x274C}, {0x274E, 0x274E}, {0x2753, 0x2755},
{0x2757, 0x2757}, {0x2763, 0x2767}, {0x2795, 0x2797},
{0x27A1, 0x27A1}, {0x27B0, 0x27B0}, {0x27BF, 0x27BF},
{0x2934, 0x2935}, {0x2B05, 0x2B07}, {0x2B1B, 0x2B1C},
{0x2B50, 0x2B50}, {0x2B55, 0x2B55}, {0x3030, 0x3030},
{0x303D, 0x303D}, {0x3297, 0x3297}, {0x3299, 0x3299},
{0x1F000, 0x1F0FF}, {0x1F10D, 0x1F10F}, {0x1F12F, 0x1F12F},
{0x1F16C, 0x1F171}, {0x1F17E, 0x1F17F}, {0x1F18E, 0x1F18E},
{0x1F191, 0x1F19A}, {0x1F1AD, 0x1F1E5}, {0x1F201, 0x1F20F},
{0x1F21A, 0x1F21A}, {0x1F22F, 0x1F22F}, {0x1F232, 0x1F23A},
{0x1F23C, 0x1F23F}, {0x1F249, 0x1F3FA}, {0x1F400, 0x1F53D},
{0x1F546, 0x1F64F}, {0x1F680, 0x1F6FF}, {0x1F774, 0x1F77F},
{0x1F7D5, 0x1F7FF}, {0x1F80C, 0x1F80F}, {0x1F848, 0x1F84F},
{0x1F85A, 0x1F85F}, {0x1F888, 0x1F88F}, {0x1F8AE, 0x1F8FF},
{0x1F90C, 0x1F93A}, {0x1F93C, 0x1F945}, {0x1F947, 0x1FFFD},
}

View File

@ -78,14 +78,14 @@ table.Render()
```
DATE | DESCRIPTION | CV2 | AMOUNT
+----------+--------------------------+-------+---------+
-----------+--------------------------+-------+----------
1/1/2014 | Domain name | 2233 | $10.98
1/1/2014 | January Hosting | 2233 | $54.95
1/4/2014 | February Hosting | 2233 | $51.00
1/4/2014 | February Extra Bandwidth | 2233 | $30.00
+----------+--------------------------+-------+---------+
-----------+--------------------------+-------+----------
TOTAL | $146 93
+-------+---------+
--------+----------
```
@ -233,7 +233,7 @@ table.Render()
#### Table with color Output
![Table with Color](https://cloud.githubusercontent.com/assets/6460392/21101956/bbc7b356-c0a1-11e6-9f36-dba694746efc.png)
#### Example 6 - Set table caption
#### Example 7 - Set table caption
```go
data := [][]string{
[]string{"A", "The Good", "500"},
@ -254,7 +254,7 @@ table.Render() // Send output
Note: Caption text will wrap with total width of rendered table.
##### Output 6
##### Output 7
```
+------+-----------------------+--------+
| NAME | SIGN | RATING |
@ -267,6 +267,69 @@ Note: Caption text will wrap with total width of rendered table.
Movie ratings.
```
#### Example 8 - Set NoWhiteSpace and TablePadding option
```go
data := [][]string{
{"node1.example.com", "Ready", "compute", "1.11"},
{"node2.example.com", "Ready", "compute", "1.11"},
{"node3.example.com", "Ready", "compute", "1.11"},
{"node4.example.com", "NotReady", "compute", "1.11"},
}
table := tablewriter.NewWriter(os.Stdout)
table.SetHeader([]string{"Name", "Status", "Role", "Version"})
table.SetAutoWrapText(false)
table.SetAutoFormatHeaders(true)
table.SetHeaderAlignment(ALIGN_LEFT)
table.SetAlignment(ALIGN_LEFT)
table.SetCenterSeparator("")
table.SetColumnSeparator("")
table.SetRowSeparator("")
table.SetHeaderLine(false)
table.SetBorder(false)
table.SetTablePadding("\t") // pad with tabs
table.SetNoWhiteSpace(true)
table.AppendBulk(data) // Add Bulk Data
table.Render()
```
##### Output 8
```
NAME STATUS ROLE VERSION
node1.example.com Ready compute 1.11
node2.example.com Ready compute 1.11
node3.example.com Ready compute 1.11
node4.example.com NotReady compute 1.11
```
#### Render table into a string
Instead of rendering the table to `io.Stdout` you can also render it into a string. Go 1.10 introduced the `strings.Builder` type which implements the `io.Writer` interface and can therefore be used for this task. Example:
```go
package main
import (
"strings"
"fmt"
"github.com/olekukonko/tablewriter"
)
func main() {
tableString := &strings.Builder{}
table := tablewriter.NewWriter(tableString)
/*
* Code to fill the table
*/
table.Render()
fmt.Println(tableString.String())
}
```
#### TODO
- ~~Import Directly from CSV~~ - `done`
- ~~Support for `SetFooter`~~ - `done`

8
vendor/github.com/olekukonko/tablewriter/go.mod generated vendored Normal file
View File

@ -0,0 +1,8 @@
module github.com/olekukonko/tablewriter
go 1.12
require (
github.com/mattn/go-runewidth v0.0.4
github.com/olekukonko/tablewriter v0.0.1
)

4
vendor/github.com/olekukonko/tablewriter/go.sum generated vendored Normal file
View File

@ -0,0 +1,4 @@
github.com/mattn/go-runewidth v0.0.4 h1:2BvfKmzob6Bmd4YsL0zygOqfdFnK7GR4QL06Do4/p7Y=
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/olekukonko/tablewriter v0.0.1 h1:b3iUnf1v+ppJiOfNX4yxxqfWKMQPZR5yoh8urCTFX88=
github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=

View File

@ -72,6 +72,8 @@ type Table struct {
newLine string
rowLine bool
autoMergeCells bool
noWhiteSpace bool
tablePadding string
hdrLine bool
borders Border
colSize int
@ -225,6 +227,16 @@ func (t *Table) SetAlignment(align int) {
t.align = align
}
// Set No White Space
func (t *Table) SetNoWhiteSpace(allow bool) {
t.noWhiteSpace = allow
}
// Set Table Padding
func (t *Table) SetTablePadding(padding string) {
t.tablePadding = padding
}
func (t *Table) SetColumnAlignment(keys []int) {
for _, v := range keys {
switch v {
@ -319,16 +331,29 @@ func (t *Table) ClearFooter() {
t.footers = [][]string{}
}
// Center based on position and border.
func (t *Table) center(i int) string {
if i == -1 && !t.borders.Left {
return t.pRow
}
if i == len(t.cs)-1 && !t.borders.Right {
return t.pRow
}
return t.pCenter
}
// Print line based on row width
func (t *Table) printLine(nl bool) {
fmt.Fprint(t.out, t.pCenter)
fmt.Fprint(t.out, t.center(-1))
for i := 0; i < len(t.cs); i++ {
v := t.cs[i]
fmt.Fprintf(t.out, "%s%s%s%s",
t.pRow,
strings.Repeat(string(t.pRow), v),
t.pRow,
t.pCenter)
t.center(i))
}
if nl {
fmt.Fprint(t.out, t.newLine)
@ -398,11 +423,14 @@ func (t *Table) printHeading() {
for x := 0; x < max; x++ {
// Check if border is set
// Replace with space if not set
fmt.Fprint(t.out, ConditionString(t.borders.Left, t.pColumn, SPACE))
if !t.noWhiteSpace {
fmt.Fprint(t.out, ConditionString(t.borders.Left, t.pColumn, SPACE))
}
for y := 0; y <= end; y++ {
v := t.cs[y]
h := ""
if y < len(t.headers) && x < len(t.headers[y]) {
h = t.headers[y][x]
}
@ -410,15 +438,30 @@ func (t *Table) printHeading() {
h = Title(h)
}
pad := ConditionString((y == end && !t.borders.Left), SPACE, t.pColumn)
if t.noWhiteSpace {
pad = ConditionString((y == end && !t.borders.Left), SPACE, t.tablePadding)
}
if is_esc_seq {
fmt.Fprintf(t.out, " %s %s",
format(padFunc(h, SPACE, v),
t.headerParams[y]), pad)
if !t.noWhiteSpace {
fmt.Fprintf(t.out, " %s %s",
format(padFunc(h, SPACE, v),
t.headerParams[y]), pad)
} else {
fmt.Fprintf(t.out, "%s %s",
format(padFunc(h, SPACE, v),
t.headerParams[y]), pad)
}
} else {
fmt.Fprintf(t.out, " %s %s",
padFunc(h, SPACE, v),
pad)
if !t.noWhiteSpace {
fmt.Fprintf(t.out, " %s %s",
padFunc(h, SPACE, v),
pad)
} else {
// the spaces between breaks the kube formatting
fmt.Fprintf(t.out, "%s%s",
padFunc(h, SPACE, v),
pad)
}
}
}
// Next line
@ -517,6 +560,9 @@ func (t *Table) printFooter() {
// Print first junction
if i == 0 {
if length > 0 && !t.borders.Left {
center = t.pRow
}
fmt.Fprint(t.out, center)
}
@ -524,16 +570,27 @@ func (t *Table) printFooter() {
if length == 0 {
pad = SPACE
}
// Ignore left space of it has printed before
// Ignore left space as it has printed before
if hasPrinted || t.borders.Left {
pad = t.pRow
center = t.pCenter
}
// Change Center end position
if center != SPACE {
if i == end && !t.borders.Right {
center = t.pRow
}
}
// Change Center start position
if center == SPACE {
if i < end && len(t.footers[i+1][0]) != 0 {
center = t.pCenter
if !t.borders.Left {
center = t.pRow
} else {
center = t.pCenter
}
}
}
@ -627,9 +684,11 @@ func (t *Table) printRow(columns [][]string, rowIdx int) {
for y := 0; y < total; y++ {
// Check if border is set
fmt.Fprint(t.out, ConditionString((!t.borders.Left && y == 0), SPACE, t.pColumn))
if !t.noWhiteSpace {
fmt.Fprint(t.out, ConditionString((!t.borders.Left && y == 0), SPACE, t.pColumn))
fmt.Fprintf(t.out, SPACE)
}
fmt.Fprintf(t.out, SPACE)
str := columns[y][x]
// Embedding escape sequence with column value
@ -661,11 +720,17 @@ func (t *Table) printRow(columns [][]string, rowIdx int) {
}
}
fmt.Fprintf(t.out, SPACE)
if !t.noWhiteSpace {
fmt.Fprintf(t.out, SPACE)
} else {
fmt.Fprintf(t.out, t.tablePadding)
}
}
// Check if border is set
// Replace with space if not set
fmt.Fprint(t.out, ConditionString(t.borders.Left, t.pColumn, SPACE))
if !t.noWhiteSpace {
fmt.Fprint(t.out, ConditionString(t.borders.Left, t.pColumn, SPACE))
}
fmt.Fprint(t.out, t.newLine)
}
@ -706,6 +771,11 @@ func (t *Table) printRowMergeCells(writer io.Writer, columns [][]string, rowIdx
// Pad Each Height
pads := []int{}
// Checking for ANSI escape sequences for columns
is_esc_seq := false
if len(t.columnsParams) > 0 {
is_esc_seq = true
}
for i, line := range columns {
length := len(line)
pad := max - length
@ -727,9 +797,14 @@ func (t *Table) printRowMergeCells(writer io.Writer, columns [][]string, rowIdx
str := columns[y][x]
// Embedding escape sequence with column value
if is_esc_seq {
str = format(str, t.columnsParams[y])
}
if t.autoMergeCells {
//Store the full line to merge mutli-lines cells
fullLine := strings.Join(columns[y], " ")
fullLine := strings.TrimRight(strings.Join(columns[y], " "), " ")
if len(previousLine) > y && fullLine == previousLine[y] && fullLine != "" {
// If this cell is identical to the one above but not empty, we don't display the border and keep the cell empty.
displayCellBorder = append(displayCellBorder, false)
@ -767,7 +842,7 @@ func (t *Table) printRowMergeCells(writer io.Writer, columns [][]string, rowIdx
//The new previous line is the current one
previousLine = make([]string, total)
for y := 0; y < total; y++ {
previousLine[y] = strings.Join(columns[y], " ") //Store the full line for multi-lines cells
previousLine[y] = strings.TrimRight(strings.Join(columns[y], " "), " ") //Store the full line for multi-lines cells
}
//Returns the newly added line and wether or not a border should be displayed above.
return previousLine, displayCellBorder

View File

@ -61,7 +61,7 @@ func Title(name string) string {
}
// Pad String
// Attempts to play string in the center
// Attempts to place string in the center
func Pad(s, pad string, width int) string {
gap := width - DisplayWidth(s)
if gap > 0 {
@ -73,7 +73,7 @@ func Pad(s, pad string, width int) string {
}
// Pad String Right position
// This would pace string at the left side fo the screen
// This would place string at the left side of the screen
func PadRight(s, pad string, width int) string {
gap := width - DisplayWidth(s)
if gap > 0 {
@ -83,7 +83,7 @@ func PadRight(s, pad string, width int) string {
}
// Pad String Left position
// This would pace string at the right side fo the screen
// This would place string at the right side of the screen
func PadLeft(s, pad string, width int) string {
gap := width - DisplayWidth(s)
if gap > 0 {

View File

@ -1,6 +1,13 @@
Releases
========
v1.4.0 (2019-11-04)
===================
- Add `AppendInto` function to more ergonomically build errors inside a
loop.
v1.3.0 (2019-10-29)
===================

52
vendor/go.uber.org/multierr/error.go generated vendored
View File

@ -1,4 +1,4 @@
// Copyright (c) 2017 Uber Technologies, Inc.
// Copyright (c) 2019 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@ -397,3 +397,53 @@ func Append(left error, right error) error {
errors := [2]error{left, right}
return fromSlice(errors[0:])
}
// AppendInto appends an error into the destination of an error pointer and
// returns whether the error being appended was non-nil.
//
// var err error
// multierr.AppendInto(&err, r.Close())
// multierr.AppendInto(&err, w.Close())
//
// The above is equivalent to,
//
// err := multierr.Append(r.Close(), w.Close())
//
// As AppendInto reports whether the provided error was non-nil, it may be
// used to build a multierr error in a loop more ergonomically. For example:
//
// var err error
// for line := range lines {
// var item Item
// if multierr.AppendInto(&err, parse(line, &item)) {
// continue
// }
// items = append(items, item)
// }
//
// Compare this with a verison that relies solely on Append:
//
// var err error
// for line := range lines {
// var item Item
// if parseErr := parse(line, &item); parseErr != nil {
// err = multierr.Append(err, parseErr)
// continue
// }
// items = append(items, item)
// }
func AppendInto(into *error, err error) (errored bool) {
if into == nil {
// We panic if 'into' is nil. This is not documented above
// because suggesting that the pointer must be non-nil may
// confuse users into thinking that the error that it points
// to must be non-nil.
panic("misuse of multierr.AppendInto: into pointer must not be nil")
}
if err == nil {
return false
}
*into = Append(*into, err)
return true
}

View File

@ -881,7 +881,7 @@ func inBodyIM(p *parser) bool {
p.addElement()
p.im = inFramesetIM
return true
case a.Address, a.Article, a.Aside, a.Blockquote, a.Center, a.Details, a.Dir, a.Div, a.Dl, a.Fieldset, a.Figcaption, a.Figure, a.Footer, a.Header, a.Hgroup, a.Menu, a.Nav, a.Ol, a.P, a.Section, a.Summary, a.Ul:
case a.Address, a.Article, a.Aside, a.Blockquote, a.Center, a.Details, a.Dialog, a.Dir, a.Div, a.Dl, a.Fieldset, a.Figcaption, a.Figure, a.Footer, a.Header, a.Hgroup, a.Menu, a.Nav, a.Ol, a.P, a.Section, a.Summary, a.Ul:
p.popUntil(buttonScope, a.P)
p.addElement()
case a.H1, a.H2, a.H3, a.H4, a.H5, a.H6:
@ -1137,7 +1137,7 @@ func inBodyIM(p *parser) bool {
return false
}
return true
case a.Address, a.Article, a.Aside, a.Blockquote, a.Button, a.Center, a.Details, a.Dir, a.Div, a.Dl, a.Fieldset, a.Figcaption, a.Figure, a.Footer, a.Header, a.Hgroup, a.Listing, a.Menu, a.Nav, a.Ol, a.Pre, a.Section, a.Summary, a.Ul:
case a.Address, a.Article, a.Aside, a.Blockquote, a.Button, a.Center, a.Details, a.Dialog, a.Dir, a.Div, a.Dl, a.Fieldset, a.Figcaption, a.Figure, a.Footer, a.Header, a.Hgroup, a.Listing, a.Menu, a.Nav, a.Ol, a.Pre, a.Section, a.Summary, a.Ul:
p.popUntil(defaultScope, p.tok.DataAtom)
case a.Form:
if p.oe.contains(a.Template) {

View File

@ -347,6 +347,7 @@ loop:
break loop
}
if c != '/' {
z.raw.end--
continue loop
}
if z.readRawEndTag() || z.err != nil {
@ -1067,6 +1068,11 @@ loop:
// Raw returns the unmodified text of the current token. Calling Next, Token,
// Text, TagName or TagAttr may change the contents of the returned slice.
//
// The token stream's raw bytes partition the byte stream (up until an
// ErrorToken). There are no overlaps or gaps between two consecutive token's
// raw bytes. One implication is that the byte offset of the current token is
// the sum of the lengths of all previous tokens' raw bytes.
func (z *Tokenizer) Raw() []byte {
return z.buf[z.raw.start:z.raw.end]
}

View File

@ -1,6 +1,6 @@
// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
// +build go1.13
// +build go1.13,!go1.14
package idna

4733
vendor/golang.org/x/net/idna/tables12.00.go generated vendored Normal file

File diff suppressed because it is too large Load Diff

12
vendor/golang.org/x/net/internal/socket/norace.go generated vendored Normal file
View File

@ -0,0 +1,12 @@
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build !race
package socket
func (m *Message) raceRead() {
}
func (m *Message) raceWrite() {
}

37
vendor/golang.org/x/net/internal/socket/race.go generated vendored Normal file
View File

@ -0,0 +1,37 @@
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build race
package socket
import (
"runtime"
"unsafe"
)
// This package reads and writes the Message buffers using a
// direct system call, which the race detector can't see.
// These functions tell the race detector what is going on during the syscall.
func (m *Message) raceRead() {
for _, b := range m.Buffers {
if len(b) > 0 {
runtime.RaceReadRange(unsafe.Pointer(&b[0]), len(b))
}
}
if b := m.OOB; len(b) > 0 {
runtime.RaceReadRange(unsafe.Pointer(&b[0]), len(b))
}
}
func (m *Message) raceWrite() {
for _, b := range m.Buffers {
if len(b) > 0 {
runtime.RaceWriteRange(unsafe.Pointer(&b[0]), len(b))
}
}
if b := m.OOB; len(b) > 0 {
runtime.RaceWriteRange(unsafe.Pointer(&b[0]), len(b))
}
}

View File

@ -13,6 +13,9 @@ import (
)
func (c *Conn) recvMsgs(ms []Message, flags int) (int, error) {
for i := range ms {
ms[i].raceWrite()
}
hs := make(mmsghdrs, len(ms))
var parseFn func([]byte, string) (net.Addr, error)
if c.network != "tcp" {
@ -43,6 +46,9 @@ func (c *Conn) recvMsgs(ms []Message, flags int) (int, error) {
}
func (c *Conn) sendMsgs(ms []Message, flags int) (int, error) {
for i := range ms {
ms[i].raceRead()
}
hs := make(mmsghdrs, len(ms))
var marshalFn func(net.Addr) []byte
if c.network != "tcp" {

View File

@ -12,6 +12,7 @@ import (
)
func (c *Conn) recvMsg(m *Message, flags int) error {
m.raceWrite()
var h msghdr
vs := make([]iovec, len(m.Buffers))
var sa []byte
@ -48,6 +49,7 @@ func (c *Conn) recvMsg(m *Message, flags int) error {
}
func (c *Conn) sendMsg(m *Message, flags int) error {
m.raceRead()
var h msghdr
vs := make([]iovec, len(m.Buffers))
var sa []byte

View File

@ -4,4 +4,29 @@
package socket
func probeProtocolStack() int { return 4 }
import (
"sync"
"syscall"
"unsafe"
)
// See version list in https://github.com/DragonFlyBSD/DragonFlyBSD/blob/master/sys/sys/param.h
var (
osreldateOnce sync.Once
osreldate uint32
)
// First __DragonFly_version after September 2019 ABI changes
// http://lists.dragonflybsd.org/pipermail/users/2019-September/358280.html
const _dragonflyABIChangeVersion = 500705
func probeProtocolStack() int {
osreldateOnce.Do(func() { osreldate, _ = syscall.SysctlUint32("kern.osreldate") })
var p uintptr
if int(unsafe.Sizeof(p)) == 8 && osreldate >= _dragonflyABIChangeVersion {
return int(unsafe.Sizeof(p))
}
// 64-bit Dragonfly before the September 2019 ABI changes still requires
// 32-bit aligned access to network subsystem.
return 4
}

View File

@ -53,7 +53,6 @@ type sockaddrInet6 struct {
const (
sizeofIovec = 0x10
sizeofMsghdr = 0x30
sizeofMmsghdr = 0x38
sizeofCmsghdr = 0xc
sizeofSockaddrInet = 0x10

View File

@ -47,7 +47,6 @@ type sockaddrInet6 struct {
const (
sizeofIovec = 0x8
sizeofMsghdr = 0x1c
sizeofMmsghdr = 0x20
sizeofCmsghdr = 0xc
sizeofSockaddrInet = 0x10

View File

@ -50,7 +50,6 @@ type sockaddrInet6 struct {
const (
sizeofIovec = 0x10
sizeofMsghdr = 0x38
sizeofMmsghdr = 0x40
sizeofCmsghdr = 0x10
sizeofSockaddrInet = 0x10

View File

@ -45,9 +45,9 @@ type sockaddrInet6 struct {
}
const (
sizeofIovec = 0x8
sizeofMsghdr = 0x1c
sizeofMmsghdr = 0x20
sizeofIovec = 0x8
sizeofMsghdr = 0x1c
sizeofCmsghdr = 0xc
sizeofSockaddrInet = 0x10

View File

@ -48,9 +48,9 @@ type sockaddrInet6 struct {
}
const (
sizeofIovec = 0x10
sizeofMsghdr = 0x38
sizeofMmsghdr = 0x40
sizeofIovec = 0x10
sizeofMsghdr = 0x38
sizeofCmsghdr = 0x10
sizeofSockaddrInet = 0x10

View File

@ -45,9 +45,9 @@ type sockaddrInet6 struct {
}
const (
sizeofIovec = 0x8
sizeofMsghdr = 0x1c
sizeofMmsghdr = 0x20
sizeofIovec = 0x8
sizeofMsghdr = 0x1c
sizeofCmsghdr = 0xc
sizeofSockaddrInet = 0x10

View File

@ -48,9 +48,9 @@ type sockaddrInet6 struct {
}
const (
sizeofIovec = 0x10
sizeofMsghdr = 0x38
sizeofMmsghdr = 0x40
sizeofIovec = 0x10
sizeofMsghdr = 0x38
sizeofCmsghdr = 0x10
sizeofSockaddrInet = 0x10

View File

@ -48,9 +48,9 @@ type sockaddrInet6 struct {
}
const (
sizeofIovec = 0x10
sizeofMsghdr = 0x38
sizeofMmsghdr = 0x40
sizeofIovec = 0x10
sizeofMsghdr = 0x38
sizeofCmsghdr = 0x10
sizeofSockaddrInet = 0x10

View File

@ -45,9 +45,9 @@ type sockaddrInet6 struct {
}
const (
sizeofIovec = 0x8
sizeofMsghdr = 0x1c
sizeofMmsghdr = 0x20
sizeofIovec = 0x8
sizeofMsghdr = 0x1c
sizeofCmsghdr = 0xc
sizeofSockaddrInet = 0x10

View File

@ -48,9 +48,9 @@ type sockaddrInet6 struct {
}
const (
sizeofIovec = 0x10
sizeofMsghdr = 0x38
sizeofMmsghdr = 0x40
sizeofIovec = 0x10
sizeofMsghdr = 0x38
sizeofCmsghdr = 0x10
sizeofSockaddrInet = 0x10

View File

@ -48,9 +48,9 @@ type sockaddrInet6 struct {
}
const (
sizeofIovec = 0x10
sizeofMsghdr = 0x38
sizeofMmsghdr = 0x40
sizeofIovec = 0x10
sizeofMsghdr = 0x38
sizeofCmsghdr = 0x10
sizeofSockaddrInet = 0x10

View File

@ -49,9 +49,9 @@ type sockaddrInet6 struct {
}
const (
sizeofIovec = 0x10
sizeofMsghdr = 0x38
sizeofMmsghdr = 0x40
sizeofIovec = 0x10
sizeofMsghdr = 0x38
sizeofCmsghdr = 0x10
sizeofSockaddrInet = 0x10

View File

@ -48,9 +48,9 @@ type sockaddrInet6 struct {
}
const (
sizeofIovec = 0x10
sizeofMsghdr = 0x38
sizeofMmsghdr = 0x40
sizeofIovec = 0x10
sizeofMsghdr = 0x38
sizeofCmsghdr = 0x10
sizeofSockaddrInet = 0x10

View File

@ -47,9 +47,9 @@ type sockaddrInet6 struct {
}
const (
sizeofIovec = 0x8
sizeofMsghdr = 0x1c
sizeofMmsghdr = 0x20
sizeofIovec = 0x8
sizeofMsghdr = 0x1c
sizeofCmsghdr = 0xc
sizeofSockaddrInet = 0x10

View File

@ -50,9 +50,9 @@ type sockaddrInet6 struct {
}
const (
sizeofIovec = 0x10
sizeofMsghdr = 0x30
sizeofMmsghdr = 0x40
sizeofIovec = 0x10
sizeofMsghdr = 0x30
sizeofCmsghdr = 0xc
sizeofSockaddrInet = 0x10

View File

@ -47,9 +47,9 @@ type sockaddrInet6 struct {
}
const (
sizeofIovec = 0x8
sizeofMsghdr = 0x1c
sizeofMmsghdr = 0x20
sizeofIovec = 0x8
sizeofMsghdr = 0x1c
sizeofCmsghdr = 0xc
sizeofSockaddrInet = 0x10

View File

@ -52,7 +52,6 @@ type sockaddrInet6 struct {
const (
sizeofIovec = 0x10
sizeofMsghdr = 0x30
sizeofMmsghdr = 0x40
sizeofCmsghdr = 0xc
sizeofSockaddrInet = 0x10

View File

@ -35,6 +35,7 @@ func marshalInterface(b []byte, cm *ControlMessage) []byte {
}
func parseInterface(cm *ControlMessage, b []byte) {
sadl := (*syscall.SockaddrDatalink)(unsafe.Pointer(&b[0]))
var sadl syscall.SockaddrDatalink
copy((*[unsafe.Sizeof(sadl)]byte)(unsafe.Pointer(&sadl))[:], b)
cm.IfIndex = int(sadl.Index)
}

View File

@ -11,13 +11,14 @@ import (
"golang.org/x/net/bpf"
"golang.org/x/net/internal/socket"
"golang.org/x/sys/unix"
)
func (so *sockOpt) setAttachFilter(c *socket.Conn, f []bpf.RawInstruction) error {
prog := sockFProg{
prog := unix.SockFprog{
Len: uint16(len(f)),
Filter: (*sockFilter)(unsafe.Pointer(&f[0])),
Filter: (*unix.SockFilter)(unsafe.Pointer(&f[0])),
}
b := (*[sizeofSockFprog]byte)(unsafe.Pointer(&prog))[:sizeofSockFprog]
b := (*[unix.SizeofSockFprog]byte)(unsafe.Pointer(&prog))[:unix.SizeofSockFprog]
return so.Set(c, b)
}

View File

@ -11,6 +11,7 @@ import (
"golang.org/x/net/internal/iana"
"golang.org/x/net/internal/socket"
"golang.org/x/sys/unix"
)
var (
@ -35,7 +36,7 @@ var (
ssoLeaveSourceGroup: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysMCAST_LEAVE_SOURCE_GROUP, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq},
ssoBlockSourceGroup: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysMCAST_BLOCK_SOURCE, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq},
ssoUnblockSourceGroup: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysMCAST_UNBLOCK_SOURCE, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq},
ssoAttachFilter: {Option: socket.Option{Level: sysSOL_SOCKET, Name: sysSO_ATTACH_FILTER, Len: sizeofSockFprog}},
ssoAttachFilter: {Option: socket.Option{Level: unix.SOL_SOCKET, Name: unix.SO_ATTACH_FILTER, Len: unix.SizeofSockFprog}},
}
)

93
vendor/golang.org/x/net/ipv4/zsys_freebsd_arm64.go generated vendored Normal file
View File

@ -0,0 +1,93 @@
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
// cgo -godefs defs_freebsd.go
package ipv4
const (
sysIP_OPTIONS = 0x1
sysIP_HDRINCL = 0x2
sysIP_TOS = 0x3
sysIP_TTL = 0x4
sysIP_RECVOPTS = 0x5
sysIP_RECVRETOPTS = 0x6
sysIP_RECVDSTADDR = 0x7
sysIP_SENDSRCADDR = 0x7
sysIP_RETOPTS = 0x8
sysIP_RECVIF = 0x14
sysIP_ONESBCAST = 0x17
sysIP_BINDANY = 0x18
sysIP_RECVTTL = 0x41
sysIP_MINTTL = 0x42
sysIP_DONTFRAG = 0x43
sysIP_RECVTOS = 0x44
sysIP_MULTICAST_IF = 0x9
sysIP_MULTICAST_TTL = 0xa
sysIP_MULTICAST_LOOP = 0xb
sysIP_ADD_MEMBERSHIP = 0xc
sysIP_DROP_MEMBERSHIP = 0xd
sysIP_MULTICAST_VIF = 0xe
sysIP_ADD_SOURCE_MEMBERSHIP = 0x46
sysIP_DROP_SOURCE_MEMBERSHIP = 0x47
sysIP_BLOCK_SOURCE = 0x48
sysIP_UNBLOCK_SOURCE = 0x49
sysMCAST_JOIN_GROUP = 0x50
sysMCAST_LEAVE_GROUP = 0x51
sysMCAST_JOIN_SOURCE_GROUP = 0x52
sysMCAST_LEAVE_SOURCE_GROUP = 0x53
sysMCAST_BLOCK_SOURCE = 0x54
sysMCAST_UNBLOCK_SOURCE = 0x55
sizeofSockaddrStorage = 0x80
sizeofSockaddrInet = 0x10
sizeofIPMreq = 0x8
sizeofIPMreqn = 0xc
sizeofIPMreqSource = 0xc
sizeofGroupReq = 0x88
sizeofGroupSourceReq = 0x108
)
type sockaddrStorage struct {
Len uint8
Family uint8
X__ss_pad1 [6]uint8
X__ss_align int64
X__ss_pad2 [112]uint8
}
type sockaddrInet struct {
Len uint8
Family uint8
Port uint16
Addr [4]byte /* in_addr */
Zero [8]uint8
}
type ipMreq struct {
Multiaddr [4]byte /* in_addr */
Interface [4]byte /* in_addr */
}
type ipMreqn struct {
Multiaddr [4]byte /* in_addr */
Address [4]byte /* in_addr */
Ifindex int32
}
type ipMreqSource struct {
Multiaddr [4]byte /* in_addr */
Sourceaddr [4]byte /* in_addr */
Interface [4]byte /* in_addr */
}
type groupReq struct {
Interface uint32
Group sockaddrStorage
}
type groupSourceReq struct {
Interface uint32
Group sockaddrStorage
Source sockaddrStorage
}

View File

@ -55,9 +55,6 @@ const (
sysSO_EE_ORIGIN_TXSTATUS = 0x4
sysSO_EE_ORIGIN_TIMESTAMPING = 0x4
sysSOL_SOCKET = 0x1
sysSO_ATTACH_FILTER = 0x1a
sizeofKernelSockaddrStorage = 0x80
sizeofSockaddrInet = 0x10
sizeofInetPktinfo = 0xc
@ -70,8 +67,6 @@ const (
sizeofGroupSourceReq = 0x104
sizeofICMPFilter = 0x4
sizeofSockFprog = 0x8
)
type kernelSockaddrStorage struct {
@ -133,16 +128,3 @@ type groupSourceReq struct {
type icmpFilter struct {
Data uint32
}
type sockFProg struct {
Len uint16
Pad_cgo_0 [2]byte
Filter *sockFilter
}
type sockFilter struct {
Code uint16
Jt uint8
Jf uint8
K uint32
}

View File

@ -55,9 +55,6 @@ const (
sysSO_EE_ORIGIN_TXSTATUS = 0x4
sysSO_EE_ORIGIN_TIMESTAMPING = 0x4
sysSOL_SOCKET = 0x1
sysSO_ATTACH_FILTER = 0x1a
sizeofKernelSockaddrStorage = 0x80
sizeofSockaddrInet = 0x10
sizeofInetPktinfo = 0xc
@ -70,8 +67,6 @@ const (
sizeofGroupSourceReq = 0x108
sizeofICMPFilter = 0x4
sizeofSockFprog = 0x10
)
type kernelSockaddrStorage struct {
@ -135,16 +130,3 @@ type groupSourceReq struct {
type icmpFilter struct {
Data uint32
}
type sockFProg struct {
Len uint16
Pad_cgo_0 [6]byte
Filter *sockFilter
}
type sockFilter struct {
Code uint16
Jt uint8
Jf uint8
K uint32
}

View File

@ -55,9 +55,6 @@ const (
sysSO_EE_ORIGIN_TXSTATUS = 0x4
sysSO_EE_ORIGIN_TIMESTAMPING = 0x4
sysSOL_SOCKET = 0x1
sysSO_ATTACH_FILTER = 0x1a
sizeofKernelSockaddrStorage = 0x80
sizeofSockaddrInet = 0x10
sizeofInetPktinfo = 0xc
@ -70,8 +67,6 @@ const (
sizeofGroupSourceReq = 0x104
sizeofICMPFilter = 0x4
sizeofSockFprog = 0x8
)
type kernelSockaddrStorage struct {
@ -133,16 +128,3 @@ type groupSourceReq struct {
type icmpFilter struct {
Data uint32
}
type sockFProg struct {
Len uint16
Pad_cgo_0 [2]byte
Filter *sockFilter
}
type sockFilter struct {
Code uint16
Jt uint8
Jf uint8
K uint32
}

View File

@ -55,9 +55,6 @@ const (
sysSO_EE_ORIGIN_TXSTATUS = 0x4
sysSO_EE_ORIGIN_TIMESTAMPING = 0x4
sysSOL_SOCKET = 0x1
sysSO_ATTACH_FILTER = 0x1a
sizeofKernelSockaddrStorage = 0x80
sizeofSockaddrInet = 0x10
sizeofInetPktinfo = 0xc
@ -70,8 +67,6 @@ const (
sizeofGroupSourceReq = 0x108
sizeofICMPFilter = 0x4
sizeofSockFprog = 0x10
)
type kernelSockaddrStorage struct {
@ -135,16 +130,3 @@ type groupSourceReq struct {
type icmpFilter struct {
Data uint32
}
type sockFProg struct {
Len uint16
Pad_cgo_0 [6]byte
Filter *sockFilter
}
type sockFilter struct {
Code uint16
Jt uint8
Jf uint8
K uint32
}

View File

@ -55,9 +55,6 @@ const (
sysSO_EE_ORIGIN_TXSTATUS = 0x4
sysSO_EE_ORIGIN_TIMESTAMPING = 0x4
sysSOL_SOCKET = 0x1
sysSO_ATTACH_FILTER = 0x1a
sizeofKernelSockaddrStorage = 0x80
sizeofSockaddrInet = 0x10
sizeofInetPktinfo = 0xc
@ -70,8 +67,6 @@ const (
sizeofGroupSourceReq = 0x104
sizeofICMPFilter = 0x4
sizeofSockFprog = 0x8
)
type kernelSockaddrStorage struct {
@ -133,16 +128,3 @@ type groupSourceReq struct {
type icmpFilter struct {
Data uint32
}
type sockFProg struct {
Len uint16
Pad_cgo_0 [2]byte
Filter *sockFilter
}
type sockFilter struct {
Code uint16
Jt uint8
Jf uint8
K uint32
}

View File

@ -55,9 +55,6 @@ const (
sysSO_EE_ORIGIN_TXSTATUS = 0x4
sysSO_EE_ORIGIN_TIMESTAMPING = 0x4
sysSOL_SOCKET = 0x1
sysSO_ATTACH_FILTER = 0x1a
sizeofKernelSockaddrStorage = 0x80
sizeofSockaddrInet = 0x10
sizeofInetPktinfo = 0xc
@ -70,8 +67,6 @@ const (
sizeofGroupSourceReq = 0x108
sizeofICMPFilter = 0x4
sizeofSockFprog = 0x10
)
type kernelSockaddrStorage struct {
@ -135,16 +130,3 @@ type groupSourceReq struct {
type icmpFilter struct {
Data uint32
}
type sockFProg struct {
Len uint16
Pad_cgo_0 [6]byte
Filter *sockFilter
}
type sockFilter struct {
Code uint16
Jt uint8
Jf uint8
K uint32
}

View File

@ -55,9 +55,6 @@ const (
sysSO_EE_ORIGIN_TXSTATUS = 0x4
sysSO_EE_ORIGIN_TIMESTAMPING = 0x4
sysSOL_SOCKET = 0x1
sysSO_ATTACH_FILTER = 0x1a
sizeofKernelSockaddrStorage = 0x80
sizeofSockaddrInet = 0x10
sizeofInetPktinfo = 0xc
@ -70,8 +67,6 @@ const (
sizeofGroupSourceReq = 0x108
sizeofICMPFilter = 0x4
sizeofSockFprog = 0x10
)
type kernelSockaddrStorage struct {
@ -135,16 +130,3 @@ type groupSourceReq struct {
type icmpFilter struct {
Data uint32
}
type sockFProg struct {
Len uint16
Pad_cgo_0 [6]byte
Filter *sockFilter
}
type sockFilter struct {
Code uint16
Jt uint8
Jf uint8
K uint32
}

Some files were not shown because too many files have changed in this diff Show More