feat: unified chat API pt. 3 (#2535)
This commit is contained in:
parent
f9b87c4ae1
commit
a15c27c588
3
go.mod
3
go.mod
|
@ -10,12 +10,15 @@ replace github.com/docker/docker => github.com/docker/engine v1.4.2-0.2019071716
|
|||
|
||||
replace github.com/nfnt/resize => github.com/status-im/resize v0.0.0-20201215164250-7c6d9f0d3088
|
||||
|
||||
replace github.com/forPelevin/gomoji => github.com/status-im/gomoji v1.1.3-0.20220213022530-e5ac4a8732d4
|
||||
|
||||
require (
|
||||
github.com/beevik/ntp v0.2.0
|
||||
github.com/cenkalti/backoff/v3 v3.2.2
|
||||
github.com/davecgh/go-spew v1.1.1
|
||||
github.com/deckarep/golang-set v1.7.1
|
||||
github.com/ethereum/go-ethereum v1.10.13
|
||||
github.com/forPelevin/gomoji v1.1.2
|
||||
github.com/go-playground/universal-translator v0.17.0 // indirect
|
||||
github.com/golang-migrate/migrate/v4 v4.8.0 // indirect
|
||||
github.com/golang/mock v1.6.0
|
||||
|
|
2
go.sum
2
go.sum
|
@ -1218,6 +1218,8 @@ github.com/status-im/go-waku v0.0.0-20220303160403-f4f307db8734 h1:uyBsGFFH63+SH
|
|||
github.com/status-im/go-waku v0.0.0-20220303160403-f4f307db8734/go.mod h1:7SH3xYPUpUwiwSkSSuqPoJQo01ulLD5hSFDvGZzjsvo=
|
||||
github.com/status-im/go-waku-rendezvous v0.0.0-20211018070416-a93f3b70c432 h1:cbNFU38iimo9fY4B7CdF/fvIF6tNPJIZjBbpfmW2EY4=
|
||||
github.com/status-im/go-waku-rendezvous v0.0.0-20211018070416-a93f3b70c432/go.mod h1:A8t3i0CUGtXCA0aiLsP7iyikmk/KaD/2XVvNJqGCU20=
|
||||
github.com/status-im/gomoji v1.1.3-0.20220213022530-e5ac4a8732d4 h1:CtobZoiNdHpx+xurFxnuJ1xsGm3oKMfcZkB3vmomJmA=
|
||||
github.com/status-im/gomoji v1.1.3-0.20220213022530-e5ac4a8732d4/go.mod h1:hmpnZzkzSZJbFYWAUkrPV8I36x7mdYiPhPqnALP4fKA=
|
||||
github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q=
|
||||
github.com/status-im/keycard-go v0.0.0-20200402102358-957c09536969 h1:Oo2KZNP70KE0+IUJSidPj/BFS/RXNHmKIJOdckzml2E=
|
||||
github.com/status-im/keycard-go v0.0.0-20200402102358-957c09536969/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q=
|
||||
|
|
|
@ -693,6 +693,14 @@ func (db *Database) GetPublicKey() (rst string, err error) {
|
|||
return
|
||||
}
|
||||
|
||||
func (db *Database) GetPreferredUsername() (rst string, err error) {
|
||||
err = db.db.QueryRow("SELECT preferred_name FROM settings WHERE synthetic_id = 'id'").Scan(&rst)
|
||||
if err == sql.ErrNoRows {
|
||||
return rst, nil
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (db *Database) GetFleet() (rst string, err error) {
|
||||
err = db.db.QueryRow("SELECT COALESCE(fleet, '') FROM settings WHERE synthetic_id = 'id'").Scan(&rst)
|
||||
if err == sql.ErrNoRows {
|
||||
|
|
|
@ -390,7 +390,7 @@ func (b *StatusNode) gifService() *gif.Service {
|
|||
|
||||
func (b *StatusNode) ChatService() *chat.Service {
|
||||
if b.chatSrvc == nil {
|
||||
b.chatSrvc = chat.NewService()
|
||||
b.chatSrvc = chat.NewService(b.appDB)
|
||||
}
|
||||
return b.chatSrvc
|
||||
}
|
||||
|
|
|
@ -0,0 +1,159 @@
|
|||
package chat
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/forPelevin/gomoji"
|
||||
|
||||
"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"
|
||||
"github.com/status-im/status-go/protocol/common"
|
||||
"github.com/status-im/status-go/protocol/protobuf"
|
||||
)
|
||||
|
||||
type SendMessageResponse struct {
|
||||
Chat *Chat `json:"chat"`
|
||||
Messages []*common.Message `json:"messages"`
|
||||
}
|
||||
|
||||
func (api *API) SendSticker(ctx context.Context, communityID types.HexBytes, chatID string, packID int32, hash string, responseTo string) (*SendMessageResponse, error) {
|
||||
ensName, _ := api.s.accountsDB.GetPreferredUsername()
|
||||
|
||||
msg := &common.Message{
|
||||
CommunityID: string(communityID.Bytes()),
|
||||
ChatMessage: protobuf.ChatMessage{
|
||||
ChatId: chatID,
|
||||
ContentType: protobuf.ChatMessage_STICKER,
|
||||
Text: "Update to latest version to see a nice sticker here!",
|
||||
Payload: &protobuf.ChatMessage_Sticker{
|
||||
Sticker: &protobuf.StickerMessage{
|
||||
Hash: hash,
|
||||
Pack: packID,
|
||||
},
|
||||
},
|
||||
ResponseTo: responseTo,
|
||||
EnsName: ensName,
|
||||
},
|
||||
}
|
||||
|
||||
response, err := api.s.messenger.SendChatMessage(ctx, msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return api.toSendMessageResponse(response)
|
||||
|
||||
}
|
||||
|
||||
func (api *API) toSendMessageResponse(response *protocol.MessengerResponse) (*SendMessageResponse, error) {
|
||||
protocolChat := response.Chats()[0]
|
||||
|
||||
community, err := api.s.messenger.GetCommunityByID(types.HexBytes(protocolChat.CommunityID))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pubKey := types.EncodeHex(crypto.FromECDSAPub(api.s.messenger.IdentityPublicKey()))
|
||||
chat, err := api.toAPIChat(protocolChat, community, pubKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &SendMessageResponse{
|
||||
Chat: chat,
|
||||
Messages: response.Messages(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func isTextOrEmoji(text string) protobuf.ChatMessage_ContentType {
|
||||
contentType := protobuf.ChatMessage_TEXT_PLAIN
|
||||
if gomoji.RemoveEmojis(text) == "" && len(gomoji.FindAll(text)) != 0 {
|
||||
contentType = protobuf.ChatMessage_EMOJI
|
||||
}
|
||||
|
||||
return contentType
|
||||
}
|
||||
|
||||
func (api *API) SendMessage(ctx context.Context, communityID types.HexBytes, chatID string, text string, responseTo string) (*SendMessageResponse, error) {
|
||||
ensName, _ := api.s.accountsDB.GetPreferredUsername()
|
||||
|
||||
msg := &common.Message{
|
||||
CommunityID: string(communityID.Bytes()),
|
||||
ChatMessage: protobuf.ChatMessage{
|
||||
ChatId: chatID,
|
||||
ContentType: isTextOrEmoji(text),
|
||||
Text: text,
|
||||
ResponseTo: responseTo,
|
||||
EnsName: ensName,
|
||||
},
|
||||
}
|
||||
|
||||
response, err := api.s.messenger.SendChatMessage(ctx, msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return api.toSendMessageResponse(response)
|
||||
}
|
||||
|
||||
func (api *API) SendImages(ctx context.Context, communityID types.HexBytes, chatID string, imagePaths []string, text string) (*SendMessageResponse, error) {
|
||||
ensName, _ := api.s.accountsDB.GetPreferredUsername()
|
||||
|
||||
var messages []*common.Message
|
||||
|
||||
for _, imagePath := range imagePaths {
|
||||
messages = append(messages, &common.Message{
|
||||
CommunityID: string(communityID.Bytes()),
|
||||
ChatMessage: protobuf.ChatMessage{
|
||||
ChatId: chatID,
|
||||
ContentType: protobuf.ChatMessage_IMAGE,
|
||||
Text: "Update to latest version to see a nice image here!",
|
||||
EnsName: ensName,
|
||||
},
|
||||
ImagePath: imagePath,
|
||||
})
|
||||
}
|
||||
|
||||
if text != "" {
|
||||
messages = append(messages, &common.Message{
|
||||
CommunityID: string(communityID.Bytes()),
|
||||
ChatMessage: protobuf.ChatMessage{
|
||||
ChatId: chatID,
|
||||
ContentType: isTextOrEmoji(text),
|
||||
Text: text,
|
||||
EnsName: ensName,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
response, err := api.s.messenger.SendChatMessages(ctx, messages)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return api.toSendMessageResponse(response)
|
||||
|
||||
}
|
||||
|
||||
func (api *API) SendAudio(ctx context.Context, communityID types.HexBytes, chatID string, audioPath string, responseTo string) (*SendMessageResponse, error) {
|
||||
ensName, _ := api.s.accountsDB.GetPreferredUsername()
|
||||
|
||||
msg := &common.Message{
|
||||
CommunityID: string(communityID.Bytes()),
|
||||
ChatMessage: protobuf.ChatMessage{
|
||||
ChatId: chatID,
|
||||
Text: "Update to latest version to listen to an audio message here!",
|
||||
ContentType: protobuf.ChatMessage_AUDIO,
|
||||
ResponseTo: responseTo,
|
||||
EnsName: ensName,
|
||||
},
|
||||
AudioPath: audioPath,
|
||||
}
|
||||
|
||||
response, err := api.s.messenger.SendChatMessage(ctx, msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return api.toSendMessageResponse(response)
|
||||
}
|
|
@ -1,18 +1,24 @@
|
|||
package chat
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
|
||||
"github.com/ethereum/go-ethereum/p2p"
|
||||
gethrpc "github.com/ethereum/go-ethereum/rpc"
|
||||
|
||||
"github.com/status-im/status-go/multiaccounts/accounts"
|
||||
"github.com/status-im/status-go/protocol"
|
||||
)
|
||||
|
||||
func NewService() *Service {
|
||||
return &Service{}
|
||||
func NewService(appDB *sql.DB) *Service {
|
||||
return &Service{
|
||||
accountsDB: accounts.NewDB(appDB),
|
||||
}
|
||||
}
|
||||
|
||||
type Service struct {
|
||||
messenger *protocol.Messenger
|
||||
accountsDB *accounts.Database
|
||||
}
|
||||
|
||||
func (s *Service) Init(messenger *protocol.Messenger) {
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
# Binaries for programs and plugins
|
||||
*.exe
|
||||
*.exe~
|
||||
*.dll
|
||||
*.so
|
||||
*.dylib
|
||||
|
||||
# Test binary, built with `go test -c`
|
||||
*.test
|
||||
|
||||
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||
*.out
|
||||
|
||||
# Dependency directories (remove the comment below to include it)
|
||||
.idea
|
||||
.DS_Store
|
||||
vendor
|
|
@ -0,0 +1,105 @@
|
|||
# options for analysis running
|
||||
run:
|
||||
# default concurrency is a available CPU number
|
||||
concurrency: 1
|
||||
|
||||
# timeout for analysis, e.g. 30s, 5m, default is 1m
|
||||
deadline: 5m
|
||||
|
||||
# exit code when at least one issue was found, default is 1
|
||||
issues-exit-code: 1
|
||||
|
||||
# include test files or not, default is true
|
||||
tests: true
|
||||
|
||||
# which files to skip: they will be analyzed, but issues from them
|
||||
# won't be reported. Default value is empty list, but there is
|
||||
# no need to include all autogenerated files, we confidently recognize
|
||||
# autogenerated files. If it's not please let us know.
|
||||
skip-files:
|
||||
|
||||
issues:
|
||||
# Independently from option `exclude` we use default exclude patterns,
|
||||
# it can be disabled by this option. To list all
|
||||
# excluded by default patterns execute `golangci-lint run --help`.
|
||||
# Default value for this option is true.
|
||||
exclude-use-default: false
|
||||
|
||||
# output configuration options
|
||||
output:
|
||||
# colored-line-number|line-number|json|tab|checkstyle, default is "colored-line-number"
|
||||
format: colored-line-number
|
||||
|
||||
# print lines of code with issue, default is true
|
||||
print-issued-lines: true
|
||||
|
||||
# print linter name in the end of issue text, default is true
|
||||
print-linter-name: true
|
||||
|
||||
# all available settings of specific linters
|
||||
linters-settings:
|
||||
govet:
|
||||
# report about shadowed variables
|
||||
check-shadowing: true
|
||||
golint:
|
||||
# minimal confidence for issues, default is 0.8
|
||||
min-confidence: 0.8
|
||||
gofmt:
|
||||
# simplify code: gofmt with `-s` option, true by default
|
||||
simplify: true
|
||||
errcheck:
|
||||
# report about not checking of errors in type assetions: `a := b.(MyStruct)`;
|
||||
# default is false: such cases aren't reported by default.
|
||||
check-type-assertions: true
|
||||
# report about assignment of errors to blank identifier: `num, _ := strconv.Atoi(numStr)`;
|
||||
# default is false: such cases aren't reported by default.
|
||||
check-blank: false
|
||||
gocyclo:
|
||||
# minimal code complexity to report, 30 by default (but we recommend 10-20)
|
||||
min-complexity: 20
|
||||
misspell:
|
||||
# Correct spellings using locale preferences for US or UK.
|
||||
# Default is to use a neutral variety of English.
|
||||
# Setting locale to US will correct the British spelling of 'colour' to 'color'.
|
||||
locale: US
|
||||
unused:
|
||||
# treat code as a program (not a library) and report unused exported identifiers; default is false.
|
||||
# XXX: if you enable this setting, unused will report a lot of false-positives in text editors:
|
||||
# if it's called for subdir of a project it can't find funcs usages. All text editor integrations
|
||||
# with golangci-lint call it on a directory with the changed file.
|
||||
check-exported: false
|
||||
unparam:
|
||||
# Inspect exported functions, default is false. Set to true if no external program/library imports your code.
|
||||
# XXX: if you enable this setting, unparam will report a lot of false-positives in text editors:
|
||||
# if it's called for subdir of a project it can't find external interfaces. All text editor integrations
|
||||
# with golangci-lint call it on a directory with the changed file.
|
||||
check-exported: false
|
||||
nakedret:
|
||||
# make an issue if func has more lines of code than this setting and it has naked returns; default is 30
|
||||
max-func-lines: 30
|
||||
prealloc:
|
||||
# XXX: we don't recommend using this linter before doing performance profiling.
|
||||
# For most programs usage of prealloc will be a premature optimization.
|
||||
|
||||
# Report preallocation suggestions only on simple loops that have no returns/breaks/continues/gotos in them.
|
||||
# True by default.
|
||||
simple: true
|
||||
range-loops: true # Report preallocation suggestions on range loops, true by default
|
||||
for-loops: false # Report preallocation suggestions on for loops, false by default
|
||||
|
||||
linters:
|
||||
disable-all: true
|
||||
enable:
|
||||
- megacheck
|
||||
- nakedret
|
||||
- unparam
|
||||
- unused
|
||||
- govet
|
||||
- golint
|
||||
- gofmt
|
||||
- errcheck
|
||||
- gocyclo
|
||||
- ineffassign
|
||||
- deadcode
|
||||
- goimports
|
||||
fast: false
|
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2021 Vladislav Gukasov
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
|
@ -0,0 +1,13 @@
|
|||
GO_FILES=$(shell find . -name '*.go' | grep -vE 'vendor')
|
||||
|
||||
lint-fix:
|
||||
go get github.com/golangci/golangci-lint
|
||||
goimports -w $(GO_FILES)
|
||||
go fmt ./...
|
||||
golangci-lint -v run ./...
|
||||
|
||||
test:
|
||||
go test -count 1 -v -race ./...
|
||||
|
||||
bench:
|
||||
go test -bench=. -benchmem -v -run Benchmark ./...
|
|
@ -0,0 +1,193 @@
|
|||
# GoMoji
|
||||
<p align="center">work with emoji in the most convenient way</p>
|
||||
|
||||
GoMoji is a Go package that provides a [fast](#performance) and [simple](#check-string-contains-emoji) way to work with emojis in strings.
|
||||
It has features such as:
|
||||
* [check whether string contains emoji](#check-string-contains-emoji)
|
||||
* [find all emojis in string](#find-all)
|
||||
* [get all emojis](#get-all)
|
||||
* [remove all emojis from string](#remove-all-emojis)
|
||||
* [get emoji description](#get-emoji-info)
|
||||
|
||||
Getting Started
|
||||
===============
|
||||
|
||||
## Installing
|
||||
|
||||
To start using GoMoji, install Go and run `go get`:
|
||||
|
||||
```sh
|
||||
$ go get -u github.com/forPelevin/gomoji
|
||||
```
|
||||
|
||||
This will retrieve the package.
|
||||
|
||||
## Check string contains emoji
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/forPelevin/gomoji"
|
||||
)
|
||||
|
||||
func main() {
|
||||
res := gomoji.ContainsEmoji("hello world")
|
||||
println(res) // false
|
||||
|
||||
res = gomoji.ContainsEmoji("hello world 🤗")
|
||||
println(res) // true
|
||||
}
|
||||
```
|
||||
|
||||
## Find all
|
||||
The function searches for all emoji occurrences in a string. It returns a nil slice if there are no emojis.
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/forPelevin/gomoji"
|
||||
)
|
||||
|
||||
func main() {
|
||||
res := gomoji.FindAll("🧖 hello 🦋 world")
|
||||
println(res)
|
||||
}
|
||||
```
|
||||
|
||||
Result:
|
||||
|
||||
```go
|
||||
[]gomoji.Emoji{
|
||||
{
|
||||
Slug: "person-in-steamy-room",
|
||||
Character: "🧖",
|
||||
UnicodeName: "E5.0 person in steamy room",
|
||||
CodePoint: "1F9D6",
|
||||
Group: "People & Body",
|
||||
SubGroup: "person-activity",
|
||||
},
|
||||
{
|
||||
Slug: "butterfly",
|
||||
Character: "🦋",
|
||||
UnicodeName: "E3.0 butterfly",
|
||||
CodePoint: "1F98B",
|
||||
Group: "Animals & Nature",
|
||||
SubGroup: "animal-bug",
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## Get all
|
||||
The function returns all existing emojis. You can do whatever you need with the list.
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/forPelevin/gomoji"
|
||||
)
|
||||
|
||||
func main() {
|
||||
emojis := gomoji.AllEmojis()
|
||||
println(emojis)
|
||||
}
|
||||
```
|
||||
|
||||
## Remove all emojis
|
||||
|
||||
The function removes all emojis from given string:
|
||||
|
||||
```go
|
||||
res := gomoji.RemoveEmojis("🧖 hello 🦋world")
|
||||
println(res) // "hello world"
|
||||
```
|
||||
|
||||
## Get emoji info
|
||||
|
||||
The function returns info about provided emoji:
|
||||
|
||||
```go
|
||||
info, err := gomoji.GetInfo("1") // error: the string is not emoji
|
||||
info, err := gomoji.GetInfo("1️⃣")
|
||||
println(info)
|
||||
```
|
||||
|
||||
Result:
|
||||
|
||||
```go
|
||||
gomoji.Entity{
|
||||
Slug: "keycap-1",
|
||||
Character: "1️⃣",
|
||||
UnicodeName: "E0.6 keycap: 1",
|
||||
CodePoint: "0031 FE0F 20E3",
|
||||
Group: "Symbols",
|
||||
SubGroup: "keycap",
|
||||
}
|
||||
```
|
||||
|
||||
## Emoji entity
|
||||
All searching methods return the Emoji entity which contains comprehensive info about emoji.
|
||||
```go
|
||||
type Emoji struct {
|
||||
Slug string `json:"slug"`
|
||||
Character string `json:"character"`
|
||||
UnicodeName string `json:"unicode_name"`
|
||||
CodePoint string `json:"code_point"`
|
||||
Group string `json:"group"`
|
||||
SubGroup string `json:"sub_group"`
|
||||
}
|
||||
```
|
||||
Example:
|
||||
```go
|
||||
[]gomoji.Emoji{
|
||||
{
|
||||
Slug: "butterfly",
|
||||
Character: "🦋",
|
||||
UnicodeName: "E3.0 butterfly",
|
||||
CodePoint: "1F98B",
|
||||
Group: "Animals & Nature",
|
||||
SubGroup: "animal-bug",
|
||||
},
|
||||
{
|
||||
Slug: "roll-of-paper",
|
||||
Character: "🧻",
|
||||
UnicodeName: "E11.0 roll of paper",
|
||||
CodePoint: "1F9FB",
|
||||
Group: "Objects",
|
||||
SubGroup: "household",
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## Performance
|
||||
|
||||
GoMoji Benchmarks
|
||||
|
||||
```
|
||||
goos: darwin
|
||||
goarch: amd64
|
||||
pkg: github.com/forPelevin/gomoji
|
||||
cpu: Intel(R) Core(TM) i5-8257U CPU @ 1.40GHz
|
||||
BenchmarkContainsEmojiParallel
|
||||
BenchmarkContainsEmojiParallel-8 7439398 159.2 ns/op 144 B/op 3 allocs/op
|
||||
BenchmarkContainsEmoji
|
||||
BenchmarkContainsEmoji-8 2457042 482.2 ns/op 144 B/op 3 allocs/op
|
||||
BenchmarkRemoveEmojisParallel
|
||||
BenchmarkRemoveEmojisParallel-8 4589841 265.8 ns/op 236 B/op 5 allocs/op
|
||||
BenchmarkRemoveEmojis
|
||||
BenchmarkRemoveEmojis-8 1456464 831.9 ns/op 236 B/op 5 allocs/op
|
||||
BenchmarkGetInfoParallel
|
||||
BenchmarkGetInfoParallel-8 272416886 4.433 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkGetInfo
|
||||
BenchmarkGetInfo-8 64521932 19.86 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkFindAllParallel
|
||||
BenchmarkFindAllParallel-8 3989124 295.9 ns/op 456 B/op 5 allocs/op
|
||||
BenchmarkFindAll
|
||||
BenchmarkFindAll-8 1304463 913.7 ns/op 456 B/op 5 allocs/op
|
||||
```
|
||||
|
||||
## Contact
|
||||
Vlad Gukasov [@vgukasov](https://www.facebook.com/vgukasov)
|
||||
|
||||
## License
|
||||
|
||||
GoMoji source code is available under the MIT [License](/LICENSE).
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,5 @@
|
|||
module github.com/forPelevin/gomoji
|
||||
|
||||
go 1.13
|
||||
|
||||
require github.com/rivo/uniseg v0.2.0
|
|
@ -0,0 +1,2 @@
|
|||
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
|
@ -0,0 +1,89 @@
|
|||
package gomoji
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"strings"
|
||||
|
||||
"github.com/rivo/uniseg"
|
||||
)
|
||||
|
||||
// errors
|
||||
var (
|
||||
ErrStrNotEmoji = errors.New("the string is not emoji")
|
||||
)
|
||||
|
||||
// Emoji is an entity that represents comprehensive emoji info.
|
||||
type Emoji struct {
|
||||
Slug string `json:"slug"`
|
||||
Character string `json:"character"`
|
||||
UnicodeName string `json:"unicode_name"`
|
||||
CodePoint string `json:"code_point"`
|
||||
Group string `json:"group"`
|
||||
SubGroup string `json:"sub_group"`
|
||||
}
|
||||
|
||||
// ContainsEmoji checks whether given string contains emoji or not. It uses local emoji list as provider.
|
||||
func ContainsEmoji(s string) bool {
|
||||
gr := uniseg.NewGraphemes(s)
|
||||
for gr.Next() {
|
||||
if _, ok := emojiMap[gr.Str()]; ok {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// AllEmojis gets all emojis from provider.
|
||||
func AllEmojis() []Emoji {
|
||||
return emojiMapToSlice(emojiMap)
|
||||
}
|
||||
|
||||
// RemoveEmojis removes all emojis from the s string and returns a new string.
|
||||
func RemoveEmojis(s string) string {
|
||||
cleanBuf := bytes.Buffer{}
|
||||
|
||||
gr := uniseg.NewGraphemes(s)
|
||||
for gr.Next() {
|
||||
if _, ok := emojiMap[gr.Str()]; !ok {
|
||||
cleanBuf.Write(gr.Bytes())
|
||||
}
|
||||
}
|
||||
|
||||
return strings.TrimSpace(cleanBuf.String())
|
||||
}
|
||||
|
||||
// GetInfo returns a gomoji.Emoji model representation of provided emoji.
|
||||
// If the emoji was not found, it returns the gomoji.ErrStrNotEmoji error
|
||||
func GetInfo(emoji string) (Emoji, error) {
|
||||
em, ok := emojiMap[emoji]
|
||||
if !ok {
|
||||
return Emoji{}, ErrStrNotEmoji
|
||||
}
|
||||
|
||||
return em, nil
|
||||
}
|
||||
|
||||
// FindAll finds all emojis in given string. If there are no emojis it returns a nil-slice.
|
||||
func FindAll(s string) []Emoji {
|
||||
var emojis []Emoji
|
||||
|
||||
gr := uniseg.NewGraphemes(s)
|
||||
for gr.Next() {
|
||||
if em, ok := emojiMap[gr.Str()]; ok {
|
||||
emojis = append(emojis, em)
|
||||
}
|
||||
}
|
||||
|
||||
return emojis
|
||||
}
|
||||
|
||||
func emojiMapToSlice(em map[string]Emoji) []Emoji {
|
||||
emojis := make([]Emoji, 0, len(em))
|
||||
for _, emoji := range em {
|
||||
emojis = append(emojis, emoji)
|
||||
}
|
||||
|
||||
return emojis
|
||||
}
|
|
@ -120,6 +120,8 @@ github.com/fjl/memsize
|
|||
github.com/fjl/memsize/memsizeui
|
||||
# github.com/flynn/noise v1.0.0
|
||||
github.com/flynn/noise
|
||||
# github.com/forPelevin/gomoji v1.1.2 => github.com/status-im/gomoji v1.1.3-0.20220213022530-e5ac4a8732d4
|
||||
github.com/forPelevin/gomoji
|
||||
# github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08
|
||||
github.com/gballet/go-libpcsclite
|
||||
# github.com/go-ole/go-ole v1.2.5
|
||||
|
|
Loading…
Reference in New Issue