Add lark notification and bot support #532

##### ISSUE TYPE

 - Feature Pull Request

##### SUMMARY

larksuit(https://www.larksuite.com/en_us/) is a collaboration and communication platform and used by many customers in the world.  It has a friendly open platform for 3rd parity apps and bots to intergate.

The PR is adding the support of lark notification and bot  in botkube.




Fixes #XXX
This commit is contained in:
Liu Shaohui 2022-02-15 00:52:36 +08:00 committed by GitHub
parent 686193bf28
commit 0558e01664
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 508 additions and 18 deletions

View File

@ -36,7 +36,7 @@ test: system-check
# Build the binary
build: pre-build
@cd cmd/botkube;GOOS_VAL=$(shell go env GOOS) GOARCH_VAL=$(shell go env GOARCH) go build -o $(shell go env GOPATH)/bin/botkube
@cd cmd/botkube;GOOS_VAL=$(shell go env GOOS) CGO_ENABLED=0 GOARCH_VAL=$(shell go env GOARCH) go build -o $(shell go env GOPATH)/bin/botkube
@echo "Build completed successfully"
# Build the image

View File

@ -83,6 +83,12 @@ func startController() error {
go db.Start()
}
if conf.Communications.Lark.Enabled {
log.Info("Starting lark bot")
db := bot.NewLarkBot(conf)
go db.Start()
}
// Start upgrade notifier
if conf.Settings.UpgradeNotifier {
log.Info("Starting upgrade notifier")

5
go.mod
View File

@ -14,6 +14,7 @@ require (
github.com/hashicorp/golang-lru v0.5.3 // indirect
github.com/imdario/mergo v0.3.7 // indirect
github.com/infracloudio/msbotbuilder-go v0.2.5
github.com/larksuite/oapi-sdk-go v1.1.40-rc9
github.com/lib/pq v1.2.0 // indirect
github.com/mattermost/gorp v2.0.0+incompatible // indirect
github.com/mattermost/mattermost-server v5.11.1+incompatible
@ -24,7 +25,7 @@ require (
github.com/pelletier/go-toml v1.5.0 // indirect
github.com/prometheus/client_golang v1.7.1
github.com/sha1sum/aws_signing_client v0.0.0-20200229211254-f7815c59d5c1
github.com/sirupsen/logrus v1.6.0
github.com/sirupsen/logrus v1.7.0
github.com/stretchr/testify v1.7.0
go.uber.org/multierr v1.2.0 // indirect
golang.org/x/net v0.0.0-20211209124913-491a49abca63 // indirect
@ -34,7 +35,7 @@ require (
golang.org/x/text v0.3.7 // indirect
gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d // indirect
gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect
gopkg.in/yaml.v2 v2.2.8
gopkg.in/yaml.v2 v2.4.0
k8s.io/api v0.20.5
k8s.io/apimachinery v0.20.5
k8s.io/client-go v0.20.5

42
go.sum
View File

@ -103,6 +103,7 @@ github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn
github.com/decred/dcrd/dcrec/secp256k1/v3 v3.0.0 h1:sgNeV1VRMDzs6rzyPpxyM0jp317hnwiq58Filgag2xw=
github.com/decred/dcrd/dcrec/secp256k1/v3 v3.0.0/go.mod h1:J70FGZSbzsjecRTiTzER+3f1KZLNaXkuv+yeFTKoxM8=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96 h1:cenwrSVm+Z7QLSV/BsnenAOcDXdX4cMv4wP0B/5QbPg=
@ -136,6 +137,8 @@ github.com/fvbommel/sortorder v1.0.1/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui72
github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
@ -159,8 +162,13 @@ github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8
github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-openapi/swag v0.19.5 h1:lTz6Ys4CmqqCQmZPBlbQENR1/GucA2bzYTE12Pw4tFY=
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI=
github.com/go-redis/redis v6.15.2+incompatible h1:9SpNVG76gr6InJGxoZ6IuuxaCOQwDAhzyXg+Bs+0Sb4=
github.com/go-redis/redis v6.15.2+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
github.com/go-redis/redis/v8 v8.2.2/go.mod h1:ysgGY09J/QeDYbu3HikWEIPCwaeOkuNoTgKayTEaEOw=
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
@ -273,7 +281,6 @@ github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
@ -287,6 +294,7 @@ github.com/jmespath/go-jmespath v0.3.0 h1:OS12ieG61fsCg5+qLJ+SsW9NicxNkg3b25OyT2
github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68=
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
@ -298,7 +306,6 @@ github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQL
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8=
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
@ -312,6 +319,9 @@ github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 h1:SOEGU9fKiNWd/HOJuq
github.com/lann/builder v0.0.0-20180802200727-47ae307949d0/go.mod h1:dXGbAdH5GtBTC4WfIxhKZfyBF/HBFgRZSWwZ9g/He9o=
github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 h1:P6pPBnrTSX3DEVR4fDembhRWSsG5rVo6hYhAB/ADZrk=
github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0/go.mod h1:vmVJ0l/dxyfGW6FmdpVm2joNMFikkuWg0EoCKLGUMNw=
github.com/larksuite/oapi-sdk-go v1.1.40-rc9 h1:8blNxgN33RqqSAmbWix+N6dQ/fJ8YFl2veaQsyzxEDI=
github.com/larksuite/oapi-sdk-go v1.1.40-rc9/go.mod h1:7ybKAbVdKBjXuX0YrMTfnWUyCaIe/zeI1wqjNfN9XOk=
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
github.com/lestrrat-go/backoff/v2 v2.0.7 h1:i2SeK33aOFJlUNJZzf2IpXRBvqBBnaGXfY5Xaop/GsE=
github.com/lestrrat-go/backoff/v2 v2.0.7/go.mod h1:rHP/q/r9aT27n24JQLa7JhSQZCKBBOiM/uP402WwN8Y=
github.com/lestrrat-go/blackmagic v1.0.0 h1:XzdxDbuQTz0RZZEmdU7cnQxUtFUzgCSPq8RCz4BxIi4=
@ -344,6 +354,7 @@ github.com/mattermost/mattermost-server v5.11.1+incompatible h1:LPzKY0+2Tic/ik67
github.com/mattermost/mattermost-server v5.11.1+incompatible/go.mod h1:5L6MjAec+XXQwMIt791Ganu45GKsSiM+I0tLR9wUj8Y=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI=
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
@ -373,16 +384,23 @@ github.com/nicksnyder/go-i18n v1.10.1 h1:isfg77E/aCD7+0lD/D00ebR2MV5vgeQ276WYyDa
github.com/nicksnyder/go-i18n v1.10.1/go.mod h1:e4Di5xjP9oTVrC6y3C7C0HoSYXjSbhh/dU0eUV32nB4=
github.com/nlopes/slack v0.6.1-0.20191106133607-d06c2a2b3249 h1:Pr5gZa2VcmktVwq0lyC39MsN5tz356vC/pQHKvq+QBo=
github.com/nlopes/slack v0.6.1-0.20191106133607-d06c2a2b3249/go.mod h1:JzQ9m3PMAqcpeCam7UaHSuBuupz7CmpjehYMayT6YOk=
github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/olivere/elastic v6.2.21+incompatible h1:QnTuofzxOCV5FrYLywjkMxOmOWhAeild1VXxKRksK9Y=
github.com/olivere/elastic v6.2.21+incompatible/go.mod h1:J+q1zQJTgAz9woqsbVRqGeB5G1iqDKVBWLNSYW8yfJ8=
github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.11.0 h1:JAKSXpt1YjtLA7YpPiqO9ss6sNXEsPfSGdwN0UHqzrw=
github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
github.com/onsi/ginkgo v1.14.1 h1:jMU0WaQrP0a/YAEq8eJmJKjBoMs+pClEr1vDMlM/Do4=
github.com/onsi/ginkgo v1.14.1/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/onsi/gomega v1.7.0 h1:XPnZz8VVBHjVsy1vzJmRwIcSwiUO+JFfrv/xGiigmME=
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/onsi/gomega v1.10.2 h1:aY/nuoWlKJud2J6U0E3NWsjlg+0GtwXxgEqthRdzlcs=
github.com/onsi/gomega v1.10.2/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pborman/uuid v1.2.0 h1:J7Q5mO4ysT1dv8hyrUGHb9+ooztCXu1D8MY8DZYsu3g=
@ -433,8 +451,9 @@ github.com/sha1sum/aws_signing_client v0.0.0-20200229211254-f7815c59d5c1/go.mod
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I=
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM=
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
@ -463,6 +482,8 @@ github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5Cc
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
@ -474,6 +495,7 @@ go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opentelemetry.io/otel v0.11.0/go.mod h1:G8UCk+KooF2HLkgo8RHX9epABH/aRGYET7gQOqBVdB0=
go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
@ -553,6 +575,7 @@ golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
@ -594,13 +617,16 @@ golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -611,6 +637,7 @@ golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -778,7 +805,6 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
@ -793,8 +819,10 @@ gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
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/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=

View File

@ -27,10 +27,18 @@ spec:
rules:
- http:
paths:
- path: {{ .Values.ingress.urlPath }}
{{- if .Values.communications.teams.enabled }}
- path: {{ .Values.communications.teams.messagePath }}
backend:
serviceName: {{ include "botkube.fullname" . }}
servicePort: {{ .Values.communications.teams.port }}
{{- end }}
{{- if .Values.communications.lark.enabled }}
- path: {{ .Values.communications.lark.messagePath }}
backend:
serviceName: {{ include "botkube.fullname" . }}
servicePort: {{ .Values.communications.lark.port }}
{{- end }}
{{- if .Values.ingress.host }}
host: {{ .Values.ingress.host }}
{{- end }}

View File

@ -1,4 +1,4 @@
{{- if or .Values.serviceMonitor.enabled .Values.communications.teams.enabled }}
{{- if or .Values.serviceMonitor.enabled .Values.communications.teams.enabled .Values.communications.lark.enabled}}
apiVersion: v1
kind: Service
metadata:
@ -21,6 +21,10 @@ spec:
- name: "teams"
port: {{ .Values.communications.teams.port }}
{{- end }}
{{- if .Values.communications.lark.enabled }}
- name: "lark"
port: {{ .Values.communications.lark.port }}
{{- end }}
selector:
app: botkube
{{- end }}

View File

@ -311,6 +311,7 @@ communications:
enabled: false
appID: 'APPLICATION_ID'
appPassword: 'APPLICATION_PASSWORD'
messagePath: "/bots/teams"
notiftype: short
port: 3978
@ -346,23 +347,33 @@ communications:
enabled: false
url: 'WEBHOOK_URL' # e.g https://example.com:80
# Settings for lark
lark:
enabled: false
endpoint: "LARK_URL"
appID: "LARK_APP_ID"
appSecret: "LARK_APP_SECRET"
encryptKey: "LARK_ENCRYPT_KEY"
verificationToken: "LARK_VERIFICATION_TOKEN"
messagePath: "/bots/lark"
chatGroup: "LARK_CHAT_GROUP_ID"
port: 9999
service:
name: metrics
port: 2112
targetPort: 2112
# Ingress settings to expose teams endpoint
# Ingress settings to expose teams and lark endpoints
ingress:
create: false
annotations:
kubernetes.io/ingress.class: nginx
host: 'HOST'
urlPath: "/"
tls:
enabled: false
secretName: ''
serviceMonitor:
## If true, a ServiceMonitor CR is created for a BotKube
## https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#servicemonitor

224
pkg/bot/lark.go Normal file
View File

@ -0,0 +1,224 @@
// Copyright (c) 2022 InfraCloud Technologies
//
// 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.
package bot
import (
"fmt"
"net/http"
"strings"
"github.com/larksuite/oapi-sdk-go/core"
"github.com/larksuite/oapi-sdk-go/event"
eventhttpserver "github.com/larksuite/oapi-sdk-go/event/http/native"
"github.com/infracloudio/botkube/pkg/config"
"github.com/infracloudio/botkube/pkg/execute"
"github.com/infracloudio/botkube/pkg/log"
"github.com/infracloudio/botkube/pkg/utils"
)
const (
//larkEvent lark event
larkEvent = "event"
//larkChatType lark chat type
larkChatType = "chat_type"
//larkGroup lark chat type
larkGroup = "group"
//larkText lark chat message
larkText = "text_without_at_bot"
//larkOpenChatID lark chat id
larkOpenChatID = "open_chat_id"
//larkChatID lark chat id
larkChatID = "chat_id"
//larkOpenID lark user id
larkOpenID = "open_id"
//larkUsers lark users
larkUsers = "users"
//larkUserID lark user id
larkUserID = "user_id"
//larkMessage eventType When sending a message to a chat group
larkMessage = "message"
//larkAddBot eventType When a bot is added to a chat group
larkAddBot = "add_bot"
//larkP2pChatCreate eventType When a session is first created with the bot
larkP2pChatCreate = "p2p_chat_create"
//larkAddUserToChat eventType When a user is added to a chat group
larkAddUserToChat = "add_user_to_chat"
//larkStartMsg lark start message
larkStartMsg = "Hello from BotKube. Visit botkube.io to know more."
//larkAtUser lark at user message
larkAtUser = "<at user_id=\"'%s'\">'%s'</at>"
)
// LarkBot listens for user's message, execute commands and sends back the response
type LarkBot struct {
AllowKubectl bool
RestrictAccess bool
ClusterName string
DefaultNamespace string
Port int
MessagePath string
LarkClient *utils.LarkClient
}
// NewLarkBot returns new Bot object
func NewLarkBot(c *config.Config) Bot {
larkConf := c.Communications.Lark
appSettings := core.NewInternalAppSettings(core.SetAppCredentials(larkConf.AppID, larkConf.AppSecret),
core.SetAppEventKey(larkConf.VerificationToken, larkConf.EncryptKey))
conf := core.NewConfig(core.Domain(larkConf.Endpoint), appSettings, core.SetLoggerLevel(utils.GetLoggerLevel()))
return &LarkBot{
AllowKubectl: c.Settings.Kubectl.Enabled,
RestrictAccess: c.Settings.Kubectl.RestrictAccess,
ClusterName: c.Settings.ClusterName,
DefaultNamespace: c.Settings.Kubectl.DefaultNamespace,
Port: c.Communications.Lark.Port,
MessagePath: c.Communications.Lark.MessagePath,
LarkClient: utils.NewLarkClient(conf),
}
}
// Execute commands sent by users
func (l *LarkBot) Execute(e map[string]interface{}) {
event, err := accessAndTypeCastToMap(larkEvent, e)
if err != nil {
log.Errorf("Lark: AccessAndTypeCastToMap: %s", err.Error())
return
}
chatType, err := accessAndTypeCastToString(larkChatType, event)
if err != nil {
log.Errorf("Lark: AccessAndTypeCastToString: %s", err.Error())
return
}
text, err := accessAndTypeCastToString(larkText, event)
if err != nil {
log.Errorf("Lark: AccessAndTypeCastToString: %s", err.Error())
return
}
executor := execute.NewDefaultExecutor(text, l.AllowKubectl, l.RestrictAccess, l.DefaultNamespace,
l.ClusterName, config.LarkBot, "", true)
response := executor.Execute()
if chatType == larkGroup {
chatID, err := accessAndTypeCastToString(larkOpenChatID, event)
if err != nil {
log.Errorf("Lark: AccessAndTypeCastToString: %s", err.Error())
return
}
l.LarkClient.SendTextMessage(larkChatID, chatID, response)
return
}
openID, err := accessAndTypeCastToString(larkOpenID, event)
if err != nil {
log.Errorf("Lark: AccessAndTypeCastToString: %s", err.Error())
return
}
l.LarkClient.SendTextMessage(larkOpenID, openID, response)
}
// Start starts the lark server and listens for lark messages
func (l *LarkBot) Start() {
// See: https://open.larksuite.com/document/ukTMukTMukTM/ukjNxYjL5YTM24SO2EjN
// message
larkConf := l.LarkClient.Conf
event.SetTypeCallback(larkConf, larkMessage, func(ctx *core.Context, e map[string]interface{}) error {
go l.Execute(e)
return nil
})
// add_bot
event.SetTypeCallback(larkConf, larkAddBot, func(ctx *core.Context, e map[string]interface{}) error {
go l.SayHello(e)
return nil
})
// p2p_chat_create
event.SetTypeCallback(larkConf, larkP2pChatCreate, func(ctx *core.Context, e map[string]interface{}) error {
go l.SayHello(e)
return nil
})
// add_user_to_chat
event.SetTypeCallback(larkConf, larkAddUserToChat, func(ctx *core.Context, e map[string]interface{}) error {
go l.SayHello(e)
return nil
})
eventhttpserver.Register(l.MessagePath, larkConf)
log.Infof("Started lark server on port %d", l.Port)
log.Errorf("Error in lark server. %v", http.ListenAndServe(fmt.Sprintf(":%d", l.Port), nil))
}
// SayHello send welcome message to new added users
func (l *LarkBot) SayHello(e map[string]interface{}) error {
event, err := accessAndTypeCastToMap(larkEvent, e)
if err != nil {
return err
}
larkUserList, ok := event[larkUsers]
if !ok {
return fmt.Errorf("Lark user %s not found", larkUsers)
}
users, ok := larkUserList.([]interface{})
if !ok {
user, ok := event[larkUsers].(interface{})
if !ok {
return fmt.Errorf("Invalid user format. Failed to convert user into interface{}")
}
users = append(users, user)
}
var messages []string
if users == nil {
return fmt.Errorf("Lark user is nil")
}
for _, user := range users {
userMap, ok := user.(map[string]interface{})
if !ok {
log.Error("Invalid user format. Failed to convert into user into map[string]interface{}")
continue
}
openID, err := accessAndTypeCastToString(larkOpenID, userMap)
if err != nil {
log.Errorf("Lark: AccessAndTypeCastToString: %s", err.Error())
continue
}
username, err := accessAndTypeCastToString(larkUserID, userMap)
if err != nil {
log.Errorf("Lark: AccessAndTypeCastToString: %s", err.Error())
continue
}
messages = append(messages, fmt.Sprintf(larkAtUser, openID, username))
}
messages = append(messages, larkStartMsg)
chatID, err := accessAndTypeCastToString(larkChatID, event)
if err != nil {
return err
}
return l.LarkClient.SendTextMessage(larkChatID, chatID, strings.Join(messages, " "))
}

View File

@ -1,4 +1,4 @@
// Copyright (c) 2021 InfraCloud Technologies
// Copyright (c) 2022 InfraCloud Technologies
//
// 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
@ -27,3 +27,29 @@ import (
func formatCodeBlock(msg string) string {
return fmt.Sprintf("```\n%s\n```", strings.TrimSpace(msg))
}
//accessAndTypeCastToMap access and typecast of map object
func accessAndTypeCastToMap(key string, m map[string]interface{}) (map[string]interface{}, error) {
value, ok := m[key]
if !ok {
return nil, fmt.Errorf("Missing key %s in the map", key)
}
newMap, ok := value.(map[string]interface{})
if !ok {
return nil, fmt.Errorf("Failed to convert into map[string]interface{}")
}
return newMap, nil
}
//accessAndTypeCastToString access and typecast of string object
func accessAndTypeCastToString(key string, m map[string]interface{}) (string, error) {
value, ok := m[key]
if !ok {
return "", fmt.Errorf("Missing key %s in the string", key)
}
str, ok := value.(string)
if !ok {
return "", fmt.Errorf("Failed to convert into string")
}
return str, nil
}

View File

@ -68,6 +68,8 @@ const (
TeamsBot BotPlatform = "teams"
// DiscordBot bot Platform
DiscordBot BotPlatform = "discord"
// LarkBot bot platform
LarkBot BotPlatform = "lark"
)
// EventType to watch
@ -138,6 +140,7 @@ type CommunicationsConfig struct {
Webhook Webhook
Teams Teams
ElasticSearch ElasticSearch
Lark Lark
}
// Slack configuration to authentication and send notifications
@ -148,6 +151,19 @@ type Slack struct {
Token string `yaml:",omitempty"`
}
// Lark configuration to authentication and send notifications
type Lark struct {
Enabled bool
Endpoint string `yaml:"endpoint,omitempty"`
AppID string `yaml:"appID,omitempty"`
AppSecret string `yaml:"appSecret,omitempty"`
EncryptKey string `yaml:"encryptKey,omitempty"`
VerificationToken string `yaml:"verificationToken,omitempty"`
MessagePath string `yaml:"messagePath,omitempty"`
Port int
ChatGroup string `yaml:"chatGroup,omitempty"`
}
// ElasticSearch config auth settings
type ElasticSearch struct {
Enabled bool
@ -192,7 +208,7 @@ type Teams struct {
AppPassword string `yaml:"appPassword,omitempty"`
Team string
Port string
MessagePath string
MessagePath string `yaml:"messagePath,omitempty"`
NotifType NotifType `yaml:",omitempty"`
}

View File

@ -385,7 +385,7 @@ func (e *DefaultExecutor) runInfoCommand(args []string, isAuthChannel bool) stri
if isAuthChannel == false {
return ""
}
if len(args) < 2 && args[1] != string(infoList) {
if len(args) > 1 && args[1] != string(infoList) {
return IncompleteCmdMsg
}

View File

@ -111,3 +111,8 @@ func Fatalf(format string, v ...interface{}) {
func Panicf(format string, v ...interface{}) {
log.Panicf(format, v...)
}
//GetLevel logrus logLevel
func GetLevel() logrus.Level {
return log.GetLevel()
}

61
pkg/notify/lark.go Normal file
View File

@ -0,0 +1,61 @@
// Copyright (c) 2022 InfraCloud Technologies
//
// 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.
package notify
import (
"github.com/larksuite/oapi-sdk-go/core"
"github.com/infracloudio/botkube/pkg/config"
"github.com/infracloudio/botkube/pkg/events"
"github.com/infracloudio/botkube/pkg/log"
"github.com/infracloudio/botkube/pkg/utils"
)
const (
//ChatID lark chat group id
ChatID = "chat_id"
)
// Lark contains LarkClient for communication with lark and receiver group name to send notification to
type Lark struct {
LarkClient *utils.LarkClient
ReceiverGroup string
}
// NewLark returns new Lark object
func NewLark(c config.CommunicationsConfig) Notifier {
appSettings := core.NewInternalAppSettings(core.SetAppCredentials(c.Lark.AppID, c.Lark.AppSecret),
core.SetAppEventKey(c.Lark.VerificationToken, c.Lark.EncryptKey))
conf := core.NewConfig(core.Domain(c.Lark.Endpoint), appSettings, core.SetLoggerLevel(utils.GetLoggerLevel()))
return &Lark{LarkClient: utils.NewLarkClient(conf),
ReceiverGroup: c.Lark.ChatGroup}
}
// SendEvent sends event notification to lark chart group
func (l *Lark) SendEvent(event events.Event) error {
log.Debugf(">> Sending to lark: %+v", event)
return l.LarkClient.SendTextMessage(ChatID, l.ReceiverGroup, FormatShortMessage(event))
}
// SendMessage sends message to lark chart group
func (l *Lark) SendMessage(msg string) error {
log.Debugf(">> Sending to lark: %+v", msg)
return l.LarkClient.SendTextMessage(ChatID, l.ReceiverGroup, msg)
}

View File

@ -59,5 +59,8 @@ func ListNotifiers(conf config.CommunicationsConfig) []Notifier {
if conf.Webhook.Enabled {
notifiers = append(notifiers, NewWebhook(conf))
}
if conf.Lark.Enabled {
notifiers = append(notifiers, NewLark(conf))
}
return notifiers
}

97
pkg/utils/lark.go Normal file
View File

@ -0,0 +1,97 @@
// Copyright (c) 2022 InfraCloud Technologies
//
// 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.
package utils
import (
"context"
"encoding/json"
"fmt"
"github.com/larksuite/oapi-sdk-go/core"
larkconfig "github.com/larksuite/oapi-sdk-go/core/config"
im "github.com/larksuite/oapi-sdk-go/service/im/v1"
"github.com/infracloudio/botkube/pkg/log"
)
// LarkClient the client to communication with lark open platform
type LarkClient struct {
Conf *larkconfig.Config
Service *im.Service
}
// TextMessage lark text message
type TextMessage struct {
Text string `json:"text,omitempty" validate:"omitempty"`
}
// NewLarkClient returns new Lark client
func NewLarkClient(conf *larkconfig.Config) *LarkClient {
imService := im.NewService(conf)
return &LarkClient{Conf: conf, Service: imService}
}
func (lark *LarkClient) marshalTextMessage(message string) (string, error) {
content := &TextMessage{Text: message}
data, err := json.Marshal(content)
if err != nil {
return "", fmt.Errorf("Error in marshal message: %s error: %s", content, err.Error())
}
return string(data), nil
}
// SendTextMessage sending text message to lark group
// See: https://open.larksuite.com/document/ukTMukTMukTM/uUjNz4SN2MjL1YzM
func (lark *LarkClient) SendTextMessage(receiveType, receiveID, msg string) error {
content, err := lark.marshalTextMessage(msg)
if err != nil {
return fmt.Errorf("Error in sending marshal text message: %s error: %s", msg, err.Error())
}
coreCtx := core.WrapContext(context.Background())
reqCall := lark.Service.Messages.Create(coreCtx, &im.MessageCreateReqBody{
ReceiveId: receiveID,
Content: content,
MsgType: "text",
})
reqCall.SetReceiveIdType(receiveType)
ret, err := reqCall.Do()
if err != nil {
return fmt.Errorf("Error in sending lark message: %s error: %s", msg, err.Error())
}
log.Debugf("Message successfully sent to channel: %s with message: %+v", receiveID, ret)
return nil
}
//GetLoggerLevel Unified Log Levels
func GetLoggerLevel() core.LoggerLevel {
logrusLevel := log.GetLevel()
switch int(logrusLevel) {
case 0, 1, 2:
return core.LoggerLevelError
case 3:
return core.LoggerLevelWarn
case 4:
return core.LoggerLevelInfo
case 5, 6:
return core.LoggerLevelDebug
default:
return core.LoggerLevelError
}
}