diff --git a/.gitignore b/.gitignore index 5d7ebc65..9126a863 100644 --- a/.gitignore +++ b/.gitignore @@ -27,6 +27,7 @@ go.work config.yaml +confighi /code/target/ diff --git a/code/go.mod b/code/go.mod index 0ddc315d..eb1d2c64 100644 --- a/code/go.mod +++ b/code/go.mod @@ -31,6 +31,7 @@ require ( github.com/google/pprof v0.0.0-20230309165930-d61513b1440d // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect + github.com/larksuite/oapi-sdk-go v1.1.48 // indirect github.com/leodido/go-urn v1.2.1 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mattn/go-isatty v0.0.17 // indirect diff --git a/code/go.sum b/code/go.sum index 7f870c9b..fe036337 100644 --- a/code/go.sum +++ b/code/go.sum @@ -39,6 +39,7 @@ dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/logex v1.2.0/go.mod h1:9+9sk7u7pGNWYMkh0hdiL++6OeibzJccyQU4p4MedaY= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= @@ -53,6 +54,7 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= github.com/dlclark/regexp2 v1.8.1 h1:6Lcdwya6GjPUNsBct8Lg/yRPwMhABj269AAzdGSiR+0= @@ -74,10 +76,13 @@ github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5y github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= 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/gin-gonic/gin v1.8.2 h1:UzKToD9/PoFj/V4rvlKqTRKnQYyz8Sc1MJlv4JHPtvY= github.com/gin-gonic/gin v1.8.2/go.mod h1:qw5AYuDrzRTnhvusDsrov+fDIxp9Dleuu12h8nfB398= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= @@ -85,13 +90,17 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A= 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/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= +github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho= github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA= +github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= github.com/go-playground/validator/v10 v10.11.1 h1:prmOlTVv+YjZjmRmNSF3VmspqJIxJWXmqUsHwfTRRkQ= github.com/go-playground/validator/v10 v10.11.1/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4dMGDBiPU55YFDl0WbKdWU= +github.com/go-redis/redis/v8 v8.2.2/go.mod h1:ysgGY09J/QeDYbu3HikWEIPCwaeOkuNoTgKayTEaEOw= github.com/go-sourcemap/sourcemap v2.1.3+incompatible h1:W1iEw64niKVGogNgBN3ePyLFfuisuzeidWPMPWmECqU= github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= github.com/goccy/go-json v0.10.0 h1:mXKd9Qw4NuzShiRlOXKews24ufknHO7gx30lsDyokKA= @@ -163,9 +172,11 @@ github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +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/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20220319035150-800ac71e25c2/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= +github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= @@ -182,12 +193,16 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/larksuite/oapi-sdk-gin v1.0.0 h1:pf2JyCSECZ2ra16JoQEgbl7PPaaOpoAEBno+Y91HFO0= github.com/larksuite/oapi-sdk-gin v1.0.0/go.mod h1:17QKeJMEkIYBUOrUoP0HBVErfzdu7cuJ9XiXitUwe/s= +github.com/larksuite/oapi-sdk-go v1.1.48 h1:RHRr5LW68AibBzXVRXObUpkbS6TXapl4TAyhITVvB4w= +github.com/larksuite/oapi-sdk-go v1.1.48/go.mod h1:7ybKAbVdKBjXuX0YrMTfnWUyCaIe/zeI1wqjNfN9XOk= github.com/larksuite/oapi-sdk-go/v3 v3.0.14 h1:WxRAudM5eTTBZgmXs0BRp3Pq8/sxsc0lcfIl43veDJI= github.com/larksuite/oapi-sdk-go/v3 v3.0.14/go.mod h1:FKi8vBgtkBt/xNRQUwdWvoDmsPh7/wP75Sn5IBIBQLk= +github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w= github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= @@ -195,8 +210,16 @@ github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RR github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/onsi/ginkgo v1.6.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/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= +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/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/pandodao/tokenizer-go v0.2.0 h1:NhfI8fGvQkDld2cZCag6NEU3pJ/ugU9zoY1R/zi9YCs= github.com/pandodao/tokenizer-go v0.2.0/go.mod h1:t6qFbaleKxbv0KNio2XUN/mfGM5WKv4haPXDQWVDG00= github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc= @@ -217,6 +240,7 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8= github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= +github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/spf13/afero v1.9.3 h1:41FoI0fD7OR7mGcKE/aOiLkGreyf8ifIOQmJANWogMk= github.com/spf13/afero v1.9.3/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y= github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= @@ -242,6 +266,8 @@ github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= github.com/subosito/gotenv v1.4.1 h1:jyEFiXpy21Wm81FBN71l9VoMMV8H8jG+qIK3GCpY6Qs= github.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= +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/ugorji/go/codec v1.2.8 h1:sgBJS6COt0b/P40VouWKdseidkDgHxYGm0SAglUHfP0= github.com/ugorji/go/codec v1.2.8/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -255,6 +281,7 @@ 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.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= +go.opentelemetry.io/otel v0.11.0/go.mod h1:G8UCk+KooF2HLkgo8RHX9epABH/aRGYET7gQOqBVdB0= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -304,6 +331,7 @@ golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -324,6 +352,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= @@ -359,6 +388,7 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -367,10 +397,15 @@ golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/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-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= @@ -381,6 +416,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-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -568,9 +604,14 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= 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.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/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/code/handlers/card_ai_mode_action.go b/code/handlers/card_ai_mode_action.go index f544b3cc..ae5e64ee 100644 --- a/code/handlers/card_ai_mode_action.go +++ b/code/handlers/card_ai_mode_action.go @@ -9,6 +9,11 @@ import ( larkcard "github.com/larksuite/oapi-sdk-go/v3/card" ) +//这个文件是一个处理飞书卡片消息的处理程序。它包含一个名为NewAIModeCardHandler的函数, +//该函数返回一个CardHandlerFunc,用于处理选择AI模式的卡片操作。如果卡片消息的类型是AIModeChooseKind, +//则会调用CommonProcessAIMode函数进行处理。CommonProcessAIMode函数会将选择的AI模式存储在会话缓存中, +//并回复消息告知用户已选择的AI模式。这个文件还导入了一些服务和包,包括openai和larkcard。 + // AIModeChooseKind is the kind of card action for choosing AI mode func NewAIModeCardHandler(cardMsg CardMsg, m MessageHandler) CardHandlerFunc { diff --git a/code/handlers/card_common_action.go b/code/handlers/card_common_action.go index 7d89eefd..57cf4cb1 100644 --- a/code/handlers/card_common_action.go +++ b/code/handlers/card_common_action.go @@ -8,6 +8,8 @@ import ( larkcard "github.com/larksuite/oapi-sdk-go/v3/card" ) +// 这个文件的作用是实现了一个处理卡片消息的处理器。 + type CardHandlerMeta func(cardMsg CardMsg, m MessageHandler) CardHandlerFunc type CardHandlerFunc func(ctx context.Context, cardAction *larkcard.CardAction) ( @@ -16,6 +18,9 @@ type CardHandlerFunc func(ctx context.Context, cardAction *larkcard.CardAction) var ErrNextHandler = fmt.Errorf("next handler") func NewCardHandler(m MessageHandler) CardHandlerFunc { + // 添加一个新的文本处理器 + textHandler := NewTextHandler() + handlers := []CardHandlerMeta{ NewClearCardHandler, NewPicResolutionHandler, @@ -27,6 +32,11 @@ func NewCardHandler(m MessageHandler) CardHandlerFunc { } return func(ctx context.Context, cardAction *larkcard.CardAction) (interface{}, error) { + // 首先尝试使用文本处理器处理消息 + if msg, err := textHandler(ctx, cardAction); err == nil { + return msg, nil + } + var cardMsg CardMsg actionValue := cardAction.Action.Value actionValueJson, _ := json.Marshal(actionValue) diff --git a/code/handlers/common.go b/code/handlers/common.go index d4afd121..9cda7bb5 100644 --- a/code/handlers/common.go +++ b/code/handlers/common.go @@ -8,6 +8,9 @@ import ( "strings" ) +//包含了一些处理消息的函数,这些函数用于解析从飞书API接收到的消息内容。 + +// msgFilter函数用于过滤掉消息中的@提醒 // func sendCard func msgFilter(msg string) string { //replace @到下一个非空的字段 为 '' @@ -15,6 +18,8 @@ func msgFilter(msg string) string { return regex.ReplaceAllString(msg, "") } + +// parseContent函数用于解析消息内容中的文本部分 func parseContent(content string) string { //"{\"text\":\"@_user_1 hahaha\"}", //only get text content hahaha @@ -30,6 +35,7 @@ func parseContent(content string) string { return msgFilter(text) } +// processMessage函数用于处理消息中的换行符和引号 func processMessage(msg interface{}) (string, error) { msg = strings.TrimSpace(msg.(string)) msgB, err := json.Marshal(msg) @@ -45,6 +51,8 @@ func processMessage(msg interface{}) (string, error) { return msgStr, nil } +//processNewLine和processQuote函数分别用于处理换行符和引号 + func processNewLine(msg string) string { return strings.Replace(msg, "\\n", ` `, -1) @@ -54,6 +62,7 @@ func processQuote(msg string) string { return strings.Replace(msg, "\\\"", "\"", -1) } +// processUnicode函数用于将Unicode编码转换为对应的字符 // 将字符中 \u003c 替换为 < 等等 func processUnicode(msg string) string { regex := regexp.MustCompile(`\\u[0-9a-fA-F]{4}`) @@ -65,6 +74,7 @@ func processUnicode(msg string) string { }) } +// cleanTextBlock函数用于将消息中的特殊字符进行处理 func cleanTextBlock(msg string) string { msg = processNewLine(msg) msg = processUnicode(msg) @@ -72,6 +82,7 @@ func cleanTextBlock(msg string) string { return msg } +// parseFileKey和parseImageKey函数用于解析消息中的文件和图片的key值 func parseFileKey(content string) string { var contentMap map[string]interface{} err := json.Unmarshal([]byte(content), &contentMap) @@ -99,3 +110,73 @@ func parseImageKey(content string) string { imageKey := contentMap["image_key"].(string) return imageKey } + +/* +根据你的描述,我了解到你想要修改项目中的代码,使得在收到用户文本消息后,第一个返回的消息是普通的消息回复类型,而不是飞书的卡片消息。根据你提供的代码,我发现在 NewCardHandler 函数中,我们定义了一个处理卡片消息的处理器,这个处理器会依次调用一系列的处理函数,直到找到一个能够处理当前卡片消息的处理函数为止。因此,我们需要修改 NewCardHandler 函数,使其返回一个处理普通消息的处理器,而不是处理卡片消息的处理器。 + +具体来说,我们需要将 NewCardHandler 函数中的 handlers 数组中的处理卡片消息的处理函数全部替换成处理普通消息的处理函数。这里需要根据你的具体需求来确定使用哪些处理函数。如果你想要直接回复用户发送的文本消息,可以使用 m.SendText(ctx, open_id, text) 函数,其中 open_id 是用户的唯一标识符,text 是要回复的文本消息。如果你想要回复富文本消息,可以使用 m.SendPost(ctx, open_id, post) 函数,其中 post 是要回复的富文本消息。 + +下面是修改后的代码示例: + +/Users/shiym/Documents/Feishu-OpenAI/code/handlers/card_common_action.go +package handlers + +import ( +"context" +"encoding/json" +"fmt" +) +// 这个文件的作用是实现了一个处理普通消息的处理器。 + +type MessageHandler interface { +SendText(ctx context.Context, open_id, text string) error +SendPost(ctx context.Context, open_id string, post interface{}) error +} + +type MessageHandlerFunc func(ctx context.Context, open_id string, text string) error + +func NewMessageHandler(m MessageHandler) MessageHandlerFunc { +return func(ctx context.Context, open_id string, text string) error { +return m.SendText(ctx, open_id, text) +} +} +func NewPostHandler(m MessageHandler) MessageHandlerFunc { +return func(ctx context.Context, open_id string, post interface{}) error { +return m.SendPost(ctx, open_id, post) +} +} + +var ErrNextHandler = fmt.Errorf("next handler") + +func NewCardHandler(m MessageHandler) MessageHandlerFunc { +handlers := []CardHandlerMeta{ +NewClearCardHandler, +NewPicResolutionHandler, +NewPicTextMoreHandler, +NewPicModeChangeHandler, +NewRoleTagCardHandler, +NewRoleCardHandler, +NewAIModeCardHandler, +} + +return func(ctx context.Context, cardAction *larkcard.CardAction) error { +var cardMsg CardMsg +actionValue := cardAction.Action.Value +actionValueJson, _ := json.Marshal(actionValue) +if err := json.Unmarshal(actionValueJson, &cardMsg); err != nil { +return err +} +//pp.Println(cardMsg) +for _, handler := range handlers { +h := handler(cardMsg, m) +err := h(ctx, cardAction) +if err == ErrNextHandler { +continue +} +return err +} +return nil +} +} + +*/ diff --git a/code/handlers/event_common_action.go b/code/handlers/event_common_action.go index 4f79e163..2aa26a1c 100644 --- a/code/handlers/event_common_action.go +++ b/code/handlers/event_common_action.go @@ -11,6 +11,11 @@ import ( larkim "github.com/larksuite/oapi-sdk-go/v3/service/im/v1" ) +//这个文件是一个处理消息的处理程序,它定义了一些用于处理消息的操作 + +//定义了一个MsgInfo结构体, +//它包含了处理程序的类型、消息类型、消息ID、聊天ID、解析后的查询字符串、文件键、图片键、会话ID和提到的用户列表。 + type MsgInfo struct { handlerType HandlerType msgType string @@ -28,6 +33,11 @@ type ActionInfo struct { info *MsgInfo } +// 定义了一个Action接口和一些实现了该接口的操作, +// 例如ProcessedUniqueAction、ProcessMentionAction、EmptyAction、ClearAction、 +// RolePlayAction、HelpAction、BalanceAction、RoleListAction和AIModeAction。 +// 这些操作用于执行不同的任务,例如检查消息的唯一性、判断是否应该处理消息、 +// 处理空消息、清除消息、角色扮演、提供帮助、查询余额、提供角色列表和提供AI模式列表。 type Action interface { Execute(a *ActionInfo) bool } @@ -66,7 +76,7 @@ type EmptyAction struct { /*空消息*/ func (*EmptyAction) Execute(a *ActionInfo) bool { if len(a.info.qParsed) == 0 { - sendMsg(*a.ctx, "🤖️:你想知道什么呢~", a.info.chatId) + sendMsg(*a.ctx, "🤖️Bot:为什么发个空消息呢~", a.info.chatId) fmt.Println("msgId", *a.info.msgId, "message.text is empty") return false diff --git a/code/handlers/event_msg_action.go b/code/handlers/event_msg_action.go index 71755410..5ea5f2c8 100644 --- a/code/handlers/event_msg_action.go +++ b/code/handlers/event_msg_action.go @@ -27,9 +27,13 @@ func (*MessageAction) Execute(a *ActionInfo) bool { //if new topic if len(msg) == 2 { //fmt.Println("new topic", msg[1].Content) - sendNewTopicCard(*a.ctx, a.info.sessionId, a.info.msgId, - completions.Content) - return false + + + replyMsg(*a.ctx,completions.Content, a.info.msgId) + sendNewTopicCard(ctx context.Context, msgId *string, content string) + sendNewTopicCard(*a.ctx, a.info.msgId,completions.Content) + withMainText(content) + } err = replyMsg(*a.ctx, completions.Content, a.info.msgId) if err != nil { diff --git a/code/handlers/handler.go b/code/handlers/handler.go index c3286f26..80394e70 100644 --- a/code/handlers/handler.go +++ b/code/handlers/handler.go @@ -13,6 +13,8 @@ import ( larkim "github.com/larksuite/oapi-sdk-go/v3/service/im/v1" ) +//这个文件是一个消息处理器,用于处理来自飞书IM的P2P消息。它包含一个MessageHandler结构体,其中包含了处理消息的各种方法。 + // 责任链 func chain(data *ActionInfo, actions ...Action) bool { for _, v := range actions { diff --git a/code/handlers/msg.go b/code/handlers/msg.go index 18ab272e..ab675c97 100644 --- a/code/handlers/msg.go +++ b/code/handlers/msg.go @@ -122,55 +122,8 @@ func newSimpleSendCard( return cardContent, err } -// withSplitLine 用于生成分割线 -func withSplitLine() larkcard.MessageCardElement { - splitLine := larkcard.NewMessageCardHr(). - Build() - return splitLine -} -// withHeader 用于生成消息头 -func withHeader(title string, color string) *larkcard. - MessageCardHeader { - if title == "" { - title = "🤖️机器人提醒" - } - header := larkcard.NewMessageCardHeader(). - Template(color). - Title(larkcard.NewMessageCardPlainText(). - Content(title). - Build()). - Build() - return header -} -// withNote 用于生成纯文本脚注 -func withNote(note string) larkcard.MessageCardElement { - noteElement := larkcard.NewMessageCardNote(). - Elements([]larkcard.MessageCardNoteElement{larkcard.NewMessageCardPlainText(). - Content(note). - Build()}). - Build() - return noteElement -} - -// withMainMd 用于生成markdown消息体 -func withMainMd(msg string) larkcard.MessageCardElement { - msg, i := processMessage(msg) - msg = processNewLine(msg) - if i != nil { - return nil - } - mainElement := larkcard.NewMessageCardDiv(). - Fields([]*larkcard.MessageCardField{larkcard.NewMessageCardField(). - Text(larkcard.NewMessageCardLarkMd(). - Content(msg). - Build()). - IsShort(true). - Build()}). - Build() - return mainElement -} // withMainText 用于生成纯文本消息体 func withMainText(msg string) larkcard.MessageCardElement { @@ -190,396 +143,6 @@ func withMainText(msg string) larkcard.MessageCardElement { return mainElement } -func withImageDiv(imageKey string) larkcard.MessageCardElement { - imageElement := larkcard.NewMessageCardImage(). - ImgKey(imageKey). - Alt(larkcard.NewMessageCardPlainText().Content(""). - Build()). - Preview(true). - Mode(larkcard.MessageCardImageModelCropCenter). - CompactWidth(true). - Build() - return imageElement -} - -// withMdAndExtraBtn 用于生成带有额外按钮的消息体 -func withMdAndExtraBtn(msg string, btn *larkcard. - MessageCardEmbedButton) larkcard.MessageCardElement { - msg, i := processMessage(msg) - msg = processNewLine(msg) - if i != nil { - return nil - } - mainElement := larkcard.NewMessageCardDiv(). - Fields( - []*larkcard.MessageCardField{ - larkcard.NewMessageCardField(). - Text(larkcard.NewMessageCardLarkMd(). - Content(msg). - Build()). - IsShort(true). - Build()}). - Extra(btn). - Build() - return mainElement -} - -func newBtn(content string, value map[string]interface{}, - typename larkcard.MessageCardButtonType) *larkcard. - MessageCardEmbedButton { - btn := larkcard.NewMessageCardEmbedButton(). - Type(typename). - Value(value). - Text(larkcard.NewMessageCardPlainText(). - Content(content). - Build()) - return btn -} - -func newMenu( - placeHolder string, - value map[string]interface{}, - options ...MenuOption, -) *larkcard. - MessageCardEmbedSelectMenuStatic { - var aOptionPool []*larkcard.MessageCardEmbedSelectOption - for _, option := range options { - aOption := larkcard.NewMessageCardEmbedSelectOption(). - Value(option.value). - Text(larkcard.NewMessageCardPlainText(). - Content(option.label). - Build()) - aOptionPool = append(aOptionPool, aOption) - - } - btn := larkcard.NewMessageCardEmbedSelectMenuStatic(). - MessageCardEmbedSelectMenuStatic(larkcard.NewMessageCardEmbedSelectMenuBase(). - Options(aOptionPool). - Placeholder(larkcard.NewMessageCardPlainText(). - Content(placeHolder). - Build()). - Value(value). - Build()). - Build() - return btn -} - -// 清除卡片按钮 -func withClearDoubleCheckBtn(sessionID *string) larkcard.MessageCardElement { - confirmBtn := newBtn("确认清除", map[string]interface{}{ - "value": "1", - "kind": ClearCardKind, - "chatType": UserChatType, - "sessionId": *sessionID, - }, larkcard.MessageCardButtonTypeDanger, - ) - cancelBtn := newBtn("我再想想", map[string]interface{}{ - "value": "0", - "kind": ClearCardKind, - "sessionId": *sessionID, - "chatType": UserChatType, - }, - larkcard.MessageCardButtonTypeDefault) - - actions := larkcard.NewMessageCardAction(). - Actions([]larkcard.MessageCardActionElement{confirmBtn, cancelBtn}). - Layout(larkcard.MessageCardActionLayoutBisected.Ptr()). - Build() - - return actions -} - -func withPicModeDoubleCheckBtn(sessionID *string) larkcard. - MessageCardElement { - confirmBtn := newBtn("切换模式", map[string]interface{}{ - "value": "1", - "kind": PicModeChangeKind, - "chatType": UserChatType, - "sessionId": *sessionID, - }, larkcard.MessageCardButtonTypeDanger, - ) - cancelBtn := newBtn("我再想想", map[string]interface{}{ - "value": "0", - "kind": PicModeChangeKind, - "sessionId": *sessionID, - "chatType": UserChatType, - }, - larkcard.MessageCardButtonTypeDefault) - - actions := larkcard.NewMessageCardAction(). - Actions([]larkcard.MessageCardActionElement{confirmBtn, cancelBtn}). - Layout(larkcard.MessageCardActionLayoutBisected.Ptr()). - Build() - - return actions -} - -func withOneBtn(btn *larkcard.MessageCardEmbedButton) larkcard. - MessageCardElement { - actions := larkcard.NewMessageCardAction(). - Actions([]larkcard.MessageCardActionElement{btn}). - Layout(larkcard.MessageCardActionLayoutFlow.Ptr()). - Build() - return actions -} - -//新建对话按钮 - -func withPicResolutionBtn(sessionID *string) larkcard. - MessageCardElement { - cancelMenu := newMenu("默认分辨率", - map[string]interface{}{ - "value": "0", - "kind": PicResolutionKind, - "sessionId": *sessionID, - "msgId": *sessionID, - }, - MenuOption{ - label: "256x256", - value: string(services.Resolution256), - }, - MenuOption{ - label: "512x512", - value: string(services.Resolution512), - }, - MenuOption{ - label: "1024x1024", - value: string(services.Resolution1024), - }, - ) - - actions := larkcard.NewMessageCardAction(). - Actions([]larkcard.MessageCardActionElement{cancelMenu}). - Layout(larkcard.MessageCardActionLayoutFlow.Ptr()). - Build() - return actions -} - -func withRoleTagsBtn(sessionID *string, tags ...string) larkcard. - MessageCardElement { - var menuOptions []MenuOption - - for _, tag := range tags { - menuOptions = append(menuOptions, MenuOption{ - label: tag, - value: tag, - }) - } - cancelMenu := newMenu("选择角色分类", - map[string]interface{}{ - "value": "0", - "kind": RoleTagsChooseKind, - "sessionId": *sessionID, - "msgId": *sessionID, - }, - menuOptions..., - ) - - actions := larkcard.NewMessageCardAction(). - Actions([]larkcard.MessageCardActionElement{cancelMenu}). - Layout(larkcard.MessageCardActionLayoutFlow.Ptr()). - Build() - return actions -} - -func withRoleBtn(sessionID *string, titles ...string) larkcard. - MessageCardElement { - var menuOptions []MenuOption - - for _, tag := range titles { - menuOptions = append(menuOptions, MenuOption{ - label: tag, - value: tag, - }) - } - cancelMenu := newMenu("查看内置角色", - map[string]interface{}{ - "value": "0", - "kind": RoleChooseKind, - "sessionId": *sessionID, - "msgId": *sessionID, - }, - menuOptions..., - ) - - actions := larkcard.NewMessageCardAction(). - Actions([]larkcard.MessageCardActionElement{cancelMenu}). - Layout(larkcard.MessageCardActionLayoutFlow.Ptr()). - Build() - return actions -} - -func withAIModeBtn(sessionID *string, aiModeStrs []string) larkcard.MessageCardElement { - var menuOptions []MenuOption - for _, label := range aiModeStrs { - menuOptions = append(menuOptions, MenuOption{ - label: label, - value: label, - }) - } - - cancelMenu := newMenu("选择模式", - map[string]interface{}{ - "value": "0", - "kind": AIModeChooseKind, - "sessionId": *sessionID, - "msgId": *sessionID, - }, - menuOptions..., - ) - - actions := larkcard.NewMessageCardAction(). - Actions([]larkcard.MessageCardActionElement{cancelMenu}). - Layout(larkcard.MessageCardActionLayoutFlow.Ptr()). - Build() - return actions -} - -func replyMsg(ctx context.Context, msg string, msgId *string) error { - msg, i := processMessage(msg) - if i != nil { - return i - } - client := initialization.GetLarkClient() - content := larkim.NewTextMsgBuilder(). - Text(msg). - Build() - - resp, err := client.Im.Message.Reply(ctx, larkim.NewReplyMessageReqBuilder(). - MessageId(*msgId). - Body(larkim.NewReplyMessageReqBodyBuilder(). - MsgType(larkim.MsgTypeText). - Uuid(uuid.New().String()). - Content(content). - Build()). - Build()) - - // 处理错误 - if err != nil { - fmt.Println(err) - return err - } - - // 服务端错误处理 - if !resp.Success() { - fmt.Println(resp.Code, resp.Msg, resp.RequestId()) - return errors.New(resp.Msg) - } - return nil -} - -func uploadImage(base64Str string) (*string, error) { - imageBytes, err := base64.StdEncoding.DecodeString(base64Str) - if err != nil { - fmt.Println(err) - return nil, err - } - client := initialization.GetLarkClient() - resp, err := client.Im.Image.Create(context.Background(), - larkim.NewCreateImageReqBuilder(). - Body(larkim.NewCreateImageReqBodyBuilder(). - ImageType(larkim.ImageTypeMessage). - Image(bytes.NewReader(imageBytes)). - Build()). - Build()) - - // 处理错误 - if err != nil { - fmt.Println(err) - return nil, err - } - - // 服务端错误处理 - if !resp.Success() { - fmt.Println(resp.Code, resp.Msg, resp.RequestId()) - return nil, errors.New(resp.Msg) - } - return resp.Data.ImageKey, nil -} - -func replyImage(ctx context.Context, ImageKey *string, - msgId *string) error { - //fmt.Println("sendMsg", ImageKey, msgId) - - msgImage := larkim.MessageImage{ImageKey: *ImageKey} - content, err := msgImage.String() - if err != nil { - fmt.Println(err) - return err - } - client := initialization.GetLarkClient() - - resp, err := client.Im.Message.Reply(ctx, larkim.NewReplyMessageReqBuilder(). - MessageId(*msgId). - Body(larkim.NewReplyMessageReqBodyBuilder(). - MsgType(larkim.MsgTypeImage). - Uuid(uuid.New().String()). - Content(content). - Build()). - Build()) - - // 处理错误 - if err != nil { - fmt.Println(err) - return err - } - - // 服务端错误处理 - if !resp.Success() { - fmt.Println(resp.Code, resp.Msg, resp.RequestId()) - return errors.New(resp.Msg) - } - return nil -} - -func replayImageCardByBase64(ctx context.Context, base64Str string, - msgId *string, sessionId *string, question string) error { - imageKey, err := uploadImage(base64Str) - if err != nil { - return err - } - //example := "img_v2_041b28e3-5680-48c2-9af2-497ace79333g" - //imageKey := &example - //fmt.Println("imageKey", *imageKey) - err = sendImageCard(ctx, *imageKey, msgId, sessionId, question) - if err != nil { - return err - } - return nil -} - -func replayImagePlainByBase64(ctx context.Context, base64Str string, - msgId *string) error { - imageKey, err := uploadImage(base64Str) - if err != nil { - return err - } - //example := "img_v2_041b28e3-5680-48c2-9af2-497ace79333g" - //imageKey := &example - //fmt.Println("imageKey", *imageKey) - err = replyImage(ctx, imageKey, msgId) - if err != nil { - return err - } - return nil -} - -func replayVariantImageByBase64(ctx context.Context, base64Str string, - msgId *string, sessionId *string) error { - imageKey, err := uploadImage(base64Str) - if err != nil { - return err - } - //example := "img_v2_041b28e3-5680-48c2-9af2-497ace79333g" - //imageKey := &example - //fmt.Println("imageKey", *imageKey) - err = sendVarImageCard(ctx, *imageKey, msgId, sessionId) - if err != nil { - return err - } - return nil -} - func sendMsg(ctx context.Context, msg string, chatId *string) error { //fmt.Println("sendMsg", msg, chatId) msg, i := processMessage(msg) @@ -626,155 +189,53 @@ func sendClearCacheCheckCard(ctx context.Context, replyCard(ctx, msgId, newCard) } -func sendSystemInstructionCard(ctx context.Context, - sessionId *string, msgId *string, content string) { - newCard, _ := newSendCard( - withHeader("🥷 已进入角色扮演模式", larkcard.TemplateIndigo), - withMainText(content), - withNote("请注意,这将开始一个全新的对话,您将无法利用之前话题的历史信息")) - replyCard(ctx, msgId, newCard) -} -func sendPicCreateInstructionCard(ctx context.Context, - sessionId *string, msgId *string) { - newCard, _ := newSendCard( - withHeader("🖼️ 已进入图片创作模式", larkcard.TemplateBlue), - withPicResolutionBtn(sessionId), - withNote("提醒:回复文本或图片,让AI生成相关的图片。")) - replyCard(ctx, msgId, newCard) -} - -func sendPicModeCheckCard(ctx context.Context, - sessionId *string, msgId *string) { - newCard, _ := newSendCard( - withHeader("🖼️ 机器人提醒", larkcard.TemplateBlue), - withMainMd("收到图片,是否进入图片创作模式?"), - withNote("请注意,这将开始一个全新的对话,您将无法利用之前话题的历史信息"), - withPicModeDoubleCheckBtn(sessionId)) - replyCard(ctx, msgId, newCard) -} func sendNewTopicCard(ctx context.Context, sessionId *string, msgId *string, content string) { newCard, _ := newSendCard( - withHeader("👻️ 已开启新的话题", larkcard.TemplateBlue), + withHeader("氦!已开启新的话题", larkcard.TemplateBlue), withMainText(content), withNote("提醒:点击对话框参与回复,可保持话题连贯")) replyCard(ctx, msgId, newCard) } -func sendHelpCard(ctx context.Context, - sessionId *string, msgId *string) { - newCard, _ := newSendCard( - withHeader("🎒需要帮助吗?", larkcard.TemplateBlue), - withMainMd("**我是小飞机,一款基于chatGpt技术的智能聊天机器人!**"), - withSplitLine(), - withMdAndExtraBtn( - "** 🆑 清除话题上下文**\n文本回复 *清除* 或 */clear*", - newBtn("立刻清除", map[string]interface{}{ - "value": "1", - "kind": ClearCardKind, - "chatType": UserChatType, - "sessionId": *sessionId, - }, larkcard.MessageCardButtonTypeDanger)), - withSplitLine(), - withMainMd("🤖 **AI模式选择** \n"+" 文本回复 *AI模式* 或 */ai_mode*"), - withSplitLine(), - withMainMd("🛖 **内置角色列表** \n"+" 文本回复 *角色列表* 或 */roles*"), - withSplitLine(), - withMainMd("🥷 **角色扮演模式**\n文本回复*角色扮演* 或 */system*+空格+角色信息"), - withSplitLine(), - withMainMd("🎤 **AI语音对话**\n私聊模式下直接发送语音"), - withSplitLine(), - withMainMd("🎨 **图片创作模式**\n回复*图片创作* 或 */picture*"), - withSplitLine(), - withMainMd("🎰 **Token余额查询**\n回复*余额* 或 */balance*"), - withSplitLine(), - withMainMd("🔃️ **历史话题回档** 🚧\n"+" 进入话题的回复详情页,文本回复 *恢复* 或 */reload*"), - withSplitLine(), - withMainMd("📤 **话题内容导出** 🚧\n"+" 文本回复 *导出* 或 */export*"), - withSplitLine(), - withMainMd("🎰 **连续对话与多话题模式**\n"+" 点击对话框参与回复,可保持话题连贯。同时,单独提问即可开启全新新话题"), - withSplitLine(), - withMainMd("🎒 **需要更多帮助**\n文本回复 *帮助* 或 */help*"), - ) - replyCard(ctx, msgId, newCard) -} +sendNewTopicCard(*a.ctx, a.info.sessionId, a.info.msgId, + completions.Content) -func sendImageCard(ctx context.Context, imageKey string, - msgId *string, sessionId *string, question string) error { - newCard, _ := newSimpleSendCard( - withImageDiv(imageKey), - withSplitLine(), - //再来一张 - withOneBtn(newBtn("再来一张", map[string]interface{}{ - "value": question, - "kind": PicTextMoreKind, - "chatType": UserChatType, - "msgId": *msgId, - "sessionId": *sessionId, - }, larkcard.MessageCardButtonTypePrimary)), - ) - replyCard(ctx, msgId, newCard) - return nil -} +func sendNewTopicCard(ctx context.Context, + sessionId *string, msgId *string, content string) { + // 处理消息内容,生成纯文本消息元素 + mainElement := withMainText(content) -func sendVarImageCard(ctx context.Context, imageKey string, - msgId *string, sessionId *string) error { - newCard, _ := newSimpleSendCard( - withImageDiv(imageKey), - withSplitLine(), - //再来一张 - withOneBtn(newBtn("再来一张", map[string]interface{}{ - "value": imageKey, - "kind": PicVarMoreKind, - "chatType": UserChatType, - "msgId": *msgId, - "sessionId": *sessionId, - }, larkcard.MessageCardButtonTypePrimary)), - ) - replyCard(ctx, msgId, newCard) - return nil -} + // 从纯文本消息元素中提取文本内容 + contentField := mainElement.(*larkcard.MessageCardDiv).Fields[0] + plainTextContent := contentField.Text.(*larkcard.MessageCardPlainText).Content -func sendBalanceCard(ctx context.Context, msgId *string, - balance openai.BalanceResponse) { - newCard, _ := newSendCard( - withHeader("🎰️ 余额查询", larkcard.TemplateBlue), - withMainMd(fmt.Sprintf("总额度: %.2f$", balance.TotalGranted)), - withMainMd(fmt.Sprintf("已用额度: %.2f$", balance.TotalUsed)), - withMainMd(fmt.Sprintf("可用额度: %.2f$", - balance.TotalAvailable)), - withNote(fmt.Sprintf("有效期: %s - %s", - balance.EffectiveAt.Format("2006-01-02 15:04:05"), - balance.ExpiresAt.Format("2006-01-02 15:04:05"))), - ) - replyCard(ctx, msgId, newCard) + // 发送纯文本消息 + sendMsg(ctx, plainTextContent, sessionId) } -func SendRoleTagsCard(ctx context.Context, - sessionId *string, msgId *string, roleTags []string) { - newCard, _ := newSendCard( - withHeader("🛖 请选择角色类别", larkcard.TemplateIndigo), - withRoleTagsBtn(sessionId, roleTags...), - withNote("提醒:选择角色所属分类,以便我们为您推荐更多相关角色。")) - replyCard(ctx, msgId, newCard) +// func exampleUsingWithMainText(ctx context.Context, msgId *string, content string) { +// newCard, _ := withMainText( +// withMainText(content), +// replyCard(ctx, msgId, newCard) } - -func SendRoleListCard(ctx context.Context, - sessionId *string, msgId *string, roleTag string, roleList []string) { - newCard, _ := newSendCard( - withHeader("🛖 角色列表"+" - "+roleTag, larkcard.TemplateIndigo), - withRoleBtn(sessionId, roleList...), - withNote("提醒:选择内置场景,快速进入角色扮演模式。")) - replyCard(ctx, msgId, newCard) +func withMainText(msg string) larkcard.MessageCardElement { + msg, i := processMessage(msg) + msg = cleanTextBlock(msg) + if i != nil { + return nil + } + mainElement := larkcard.NewMessageCardDiv(). + Fields([]*larkcard.MessageCardField{larkcard.NewMessageCardField(). + Text(larkcard.NewMessageCardPlainText(). + Content(msg). + Build()). + IsShort(false). + Build()}). + Build() + return mainElement } -func SendAIModeListsCard(ctx context.Context, - sessionId *string, msgId *string, aiModeStrs []string) { - newCard, _ := newSendCard( - withHeader("🤖 AI模式选择", larkcard.TemplateIndigo), - withAIModeBtn(sessionId, aiModeStrs), - withNote("提醒:选择内置模式,让AI更好的理解您的需求。")) - replyCard(ctx, msgId, newCard) -} + diff --git a/code/handlers/text_handler.go b/code/handlers/text_handler.go new file mode 100644 index 00000000..3738a21b --- /dev/null +++ b/code/handlers/text_handler.go @@ -0,0 +1,23 @@ +package handlers + +import ( + "context" + "fmt" + + lark "github.com/larksuite/oapi-sdk-go/v3" +) + +type TextHandlerFunc func(ctx context.Context, msg *lark.Msg) ( + interface{}, error) + +func NewTextHandler() TextHandlerFunc { + return func(ctx context.Context, msg *lark.Msg) (interface{}, error) { + // Handle normal messages here, e.g., return a simple text message + return &lark.Msg{ + MsgType: "text", + Content: &lark.MsgContent{ + Text: fmt.Sprintf("你发送的消息是: %s", msg.Content.Text), + }, + }, nil + } +} diff --git a/code/initialization/config.go b/code/initialization/config.go index 7635432d..d8e3a269 100644 --- a/code/initialization/config.go +++ b/code/initialization/config.go @@ -9,6 +9,10 @@ import ( "github.com/spf13/viper" ) +// 该结构体包含了一些应用程序的配置信息,例如飞书应用的 App ID、App Secret、加密密钥、验证令牌、机器人名称等等。 +// 此外,它还包含了 OpenAI API 的一些配置信息,例如 API Key、API URL 等等。 +// 这些配置信息可以通过读取配置文件或环境变量来进行设置。 + type Config struct { FeishuAppId string FeishuAppSecret string @@ -30,6 +34,10 @@ type Config struct { AzureOpenaiToken string } +// 在 LoadConfig 函数中,它使用了 viper 库来读取配置文件,并将读取到的配置信息赋值给 Config 结构体的相应字段。 +// 在 getViperStringValue、getViperStringArray、getViperIntValue 和 getViperBoolValue 函数中 +// 它们分别用于获取字符串、字符串数组、整数和布尔类型的配置信息,并在读取到的配置信息为空时,返回默认值。 + func LoadConfig(cfg string) *Config { viper.SetConfigFile(cfg) viper.ReadInConfig() @@ -72,8 +80,8 @@ func getViperStringValue(key string, defaultValue string) string { return value } -//OPENAI_KEY: sk-xxx,sk-xxx,sk-xxx -//result:[sk-xxx sk-xxx sk-xxx] +// OPENAI_KEY: sk-xxx,sk-xxx,sk-xxx +// result:[sk-xxx sk-xxx sk-xxx] func getViperStringArray(key string, defaultValue []string) []string { value := viper.GetString(key) if value == "" { diff --git a/code/initialization/gin.go b/code/initialization/gin.go index cdc93234..d3d24474 100644 --- a/code/initialization/gin.go +++ b/code/initialization/gin.go @@ -11,6 +11,11 @@ import ( "github.com/gin-gonic/gin" ) +//这个文件的作用是提供一个简单的 API,用于启动 HTTP 或 HTTPS 服务器,并且可以根据配置文件来设置服务器的一些参数。 + +// - loadCertificate(config Config) (cert tls.Certificate, err error): +// 这个函数用于加载 HTTPS 服务器的证书和私钥,并且检查证书是否过期。如果证书过期或者加载失败,函数会返回一个错误。 + func loadCertificate(config Config) (cert tls.Certificate, err error) { cert, err = tls.LoadX509KeyPair(config.CertFile, config.KeyFile) if err != nil { @@ -34,6 +39,9 @@ func loadCertificate(config Config) (cert tls.Certificate, err error) { return cert, nil } +// - startHTTPServer(config Config, r *gin.Engine) (err error): +// 这个函数用于启动 HTTP 服务器,并且监听指定的端口。如果启动失败,函数会返回一个错误。 + func startHTTPServer(config Config, r *gin.Engine) (err error) { log.Printf("http server started: http://localhost:%d/webhook/event\n", config.HttpPort) err = r.Run(fmt.Sprintf(":%d", config.HttpPort)) @@ -42,6 +50,9 @@ func startHTTPServer(config Config, r *gin.Engine) (err error) { } return nil } + +// - startHTTPSServer(config Config, r *gin.Engine) (err error): +// 这个函数用于启动 HTTPS 服务器,并且监听指定的端口。如果启动失败,函数会返回一个错误。 func startHTTPSServer(config Config, r *gin.Engine) (err error) { cert, err := loadCertificate(config) if err != nil { @@ -61,6 +72,9 @@ func startHTTPSServer(config Config, r *gin.Engine) (err error) { } return nil } + +// - StartServer(config Config, r *gin.Engine) (err error): +// 这个函数根据 config.UseHttps 的值来决定启动 HTTP 还是 HTTPS 服务器。如果启动失败,函数会返回一个错误。 func StartServer(config Config, r *gin.Engine) (err error) { if config.UseHttps { err = startHTTPSServer(config, r)