Merge branch 'feature/emoji-reactions' into develop
This commit is contained in:
commit
14e426f39f
2
Makefile
2
Makefile
|
@ -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
|
||||
|
|
|
@ -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
15
go.mod
|
@ -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
39
go.sum
|
@ -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=
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
|
@ -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")
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
|
@ -289,6 +289,5 @@ func (s *MessengerInstallationSuite) TestSyncInstallationNewMessages() {
|
|||
func(r *MessengerResponse) bool { return len(r.Messages) > 0 },
|
||||
"message not received",
|
||||
)
|
||||
|
||||
s.Require().NoError(err)
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
DROP TABLE emoji_reactions;
|
|
@ -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
|
||||
);
|
|
@ -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 {
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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,
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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,
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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=
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// +build appengine js
|
||||
// +build appengine js nacl
|
||||
|
||||
package isatty
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
// +build linux
|
||||
// +build linux aix
|
||||
// +build !appengine
|
||||
// +build !android
|
||||
|
|
@ -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.
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
module github.com/mattn/go-runewidth
|
||||
|
||||
go 1.9
|
|
@ -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
|
||||
|
|
|
@ -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},
|
||||
}
|
|
@ -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`
|
||||
|
|
|
@ -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
|
||||
)
|
|
@ -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=
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
===================
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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]
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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() {
|
||||
}
|
|
@ -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))
|
||||
}
|
||||
}
|
|
@ -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" {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -53,7 +53,6 @@ type sockaddrInet6 struct {
|
|||
const (
|
||||
sizeofIovec = 0x10
|
||||
sizeofMsghdr = 0x30
|
||||
sizeofMmsghdr = 0x38
|
||||
sizeofCmsghdr = 0xc
|
||||
|
||||
sizeofSockaddrInet = 0x10
|
||||
|
|
|
@ -47,7 +47,6 @@ type sockaddrInet6 struct {
|
|||
const (
|
||||
sizeofIovec = 0x8
|
||||
sizeofMsghdr = 0x1c
|
||||
sizeofMmsghdr = 0x20
|
||||
sizeofCmsghdr = 0xc
|
||||
|
||||
sizeofSockaddrInet = 0x10
|
||||
|
|
|
@ -50,7 +50,6 @@ type sockaddrInet6 struct {
|
|||
const (
|
||||
sizeofIovec = 0x10
|
||||
sizeofMsghdr = 0x38
|
||||
sizeofMmsghdr = 0x40
|
||||
sizeofCmsghdr = 0x10
|
||||
|
||||
sizeofSockaddrInet = 0x10
|
||||
|
|
|
@ -45,9 +45,9 @@ type sockaddrInet6 struct {
|
|||
}
|
||||
|
||||
const (
|
||||
sizeofIovec = 0x8
|
||||
sizeofMsghdr = 0x1c
|
||||
sizeofMmsghdr = 0x20
|
||||
sizeofIovec = 0x8
|
||||
sizeofMsghdr = 0x1c
|
||||
|
||||
sizeofCmsghdr = 0xc
|
||||
|
||||
sizeofSockaddrInet = 0x10
|
||||
|
|
|
@ -48,9 +48,9 @@ type sockaddrInet6 struct {
|
|||
}
|
||||
|
||||
const (
|
||||
sizeofIovec = 0x10
|
||||
sizeofMsghdr = 0x38
|
||||
sizeofMmsghdr = 0x40
|
||||
sizeofIovec = 0x10
|
||||
sizeofMsghdr = 0x38
|
||||
|
||||
sizeofCmsghdr = 0x10
|
||||
|
||||
sizeofSockaddrInet = 0x10
|
||||
|
|
|
@ -45,9 +45,9 @@ type sockaddrInet6 struct {
|
|||
}
|
||||
|
||||
const (
|
||||
sizeofIovec = 0x8
|
||||
sizeofMsghdr = 0x1c
|
||||
sizeofMmsghdr = 0x20
|
||||
sizeofIovec = 0x8
|
||||
sizeofMsghdr = 0x1c
|
||||
|
||||
sizeofCmsghdr = 0xc
|
||||
|
||||
sizeofSockaddrInet = 0x10
|
||||
|
|
|
@ -48,9 +48,9 @@ type sockaddrInet6 struct {
|
|||
}
|
||||
|
||||
const (
|
||||
sizeofIovec = 0x10
|
||||
sizeofMsghdr = 0x38
|
||||
sizeofMmsghdr = 0x40
|
||||
sizeofIovec = 0x10
|
||||
sizeofMsghdr = 0x38
|
||||
|
||||
sizeofCmsghdr = 0x10
|
||||
|
||||
sizeofSockaddrInet = 0x10
|
||||
|
|
|
@ -48,9 +48,9 @@ type sockaddrInet6 struct {
|
|||
}
|
||||
|
||||
const (
|
||||
sizeofIovec = 0x10
|
||||
sizeofMsghdr = 0x38
|
||||
sizeofMmsghdr = 0x40
|
||||
sizeofIovec = 0x10
|
||||
sizeofMsghdr = 0x38
|
||||
|
||||
sizeofCmsghdr = 0x10
|
||||
|
||||
sizeofSockaddrInet = 0x10
|
||||
|
|
|
@ -45,9 +45,9 @@ type sockaddrInet6 struct {
|
|||
}
|
||||
|
||||
const (
|
||||
sizeofIovec = 0x8
|
||||
sizeofMsghdr = 0x1c
|
||||
sizeofMmsghdr = 0x20
|
||||
sizeofIovec = 0x8
|
||||
sizeofMsghdr = 0x1c
|
||||
|
||||
sizeofCmsghdr = 0xc
|
||||
|
||||
sizeofSockaddrInet = 0x10
|
||||
|
|
|
@ -48,9 +48,9 @@ type sockaddrInet6 struct {
|
|||
}
|
||||
|
||||
const (
|
||||
sizeofIovec = 0x10
|
||||
sizeofMsghdr = 0x38
|
||||
sizeofMmsghdr = 0x40
|
||||
sizeofIovec = 0x10
|
||||
sizeofMsghdr = 0x38
|
||||
|
||||
sizeofCmsghdr = 0x10
|
||||
|
||||
sizeofSockaddrInet = 0x10
|
||||
|
|
|
@ -48,9 +48,9 @@ type sockaddrInet6 struct {
|
|||
}
|
||||
|
||||
const (
|
||||
sizeofIovec = 0x10
|
||||
sizeofMsghdr = 0x38
|
||||
sizeofMmsghdr = 0x40
|
||||
sizeofIovec = 0x10
|
||||
sizeofMsghdr = 0x38
|
||||
|
||||
sizeofCmsghdr = 0x10
|
||||
|
||||
sizeofSockaddrInet = 0x10
|
||||
|
|
|
@ -49,9 +49,9 @@ type sockaddrInet6 struct {
|
|||
}
|
||||
|
||||
const (
|
||||
sizeofIovec = 0x10
|
||||
sizeofMsghdr = 0x38
|
||||
sizeofMmsghdr = 0x40
|
||||
sizeofIovec = 0x10
|
||||
sizeofMsghdr = 0x38
|
||||
|
||||
sizeofCmsghdr = 0x10
|
||||
|
||||
sizeofSockaddrInet = 0x10
|
||||
|
|
|
@ -48,9 +48,9 @@ type sockaddrInet6 struct {
|
|||
}
|
||||
|
||||
const (
|
||||
sizeofIovec = 0x10
|
||||
sizeofMsghdr = 0x38
|
||||
sizeofMmsghdr = 0x40
|
||||
sizeofIovec = 0x10
|
||||
sizeofMsghdr = 0x38
|
||||
|
||||
sizeofCmsghdr = 0x10
|
||||
|
||||
sizeofSockaddrInet = 0x10
|
||||
|
|
|
@ -47,9 +47,9 @@ type sockaddrInet6 struct {
|
|||
}
|
||||
|
||||
const (
|
||||
sizeofIovec = 0x8
|
||||
sizeofMsghdr = 0x1c
|
||||
sizeofMmsghdr = 0x20
|
||||
sizeofIovec = 0x8
|
||||
sizeofMsghdr = 0x1c
|
||||
|
||||
sizeofCmsghdr = 0xc
|
||||
|
||||
sizeofSockaddrInet = 0x10
|
||||
|
|
|
@ -50,9 +50,9 @@ type sockaddrInet6 struct {
|
|||
}
|
||||
|
||||
const (
|
||||
sizeofIovec = 0x10
|
||||
sizeofMsghdr = 0x30
|
||||
sizeofMmsghdr = 0x40
|
||||
sizeofIovec = 0x10
|
||||
sizeofMsghdr = 0x30
|
||||
|
||||
sizeofCmsghdr = 0xc
|
||||
|
||||
sizeofSockaddrInet = 0x10
|
||||
|
|
|
@ -47,9 +47,9 @@ type sockaddrInet6 struct {
|
|||
}
|
||||
|
||||
const (
|
||||
sizeofIovec = 0x8
|
||||
sizeofMsghdr = 0x1c
|
||||
sizeofMmsghdr = 0x20
|
||||
sizeofIovec = 0x8
|
||||
sizeofMsghdr = 0x1c
|
||||
|
||||
sizeofCmsghdr = 0xc
|
||||
|
||||
sizeofSockaddrInet = 0x10
|
||||
|
|
|
@ -52,7 +52,6 @@ type sockaddrInet6 struct {
|
|||
const (
|
||||
sizeofIovec = 0x10
|
||||
sizeofMsghdr = 0x30
|
||||
sizeofMmsghdr = 0x40
|
||||
sizeofCmsghdr = 0xc
|
||||
|
||||
sizeofSockaddrInet = 0x10
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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}},
|
||||
}
|
||||
)
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
Loading…
Reference in New Issue