diff --git a/README.md b/README.md index 8a4e272..c009dbc 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,14 @@ Run Koyote with Docker: docker run -p 8081:8081 koyote:v0.1 -e KOYOTE_API_PORT=8081 -e KOYOTE_TELEGRAM_BOT_TOKEN=abc:11223344 ``` +# Chat Utils + +Bot now supports some commands: +``` +/chatID - Return current chatID +/threadID - Return current threadID (If 0 then you are in General Thread or chat without Threads support) +``` + # How Koyote works 1. Koyote receives an event from GitLab @@ -41,19 +49,12 @@ docker run -p 8081:8081 koyote:v0.1 -e KOYOTE_API_PORT=8081 -e KOYOTE_TELEGRAM_B |`KOYOTE_ENABLE_PIPELINE_NOTIFICATION`|Enable Telegram notification for PIPELINE event|true| |`KOYOTE_ENABLE_PUSH_NOTIFICATION`|Enable Telegram notification for PUSH event|false| |`KOYOTE_ENABLE_TAG_PUSH_NOTIFICATION`|Enable Telegram notification for TAG PUSH event|false| -|`KOYOTE_REDIS_ENABLED`|Enable Redis for Event pooling if Telegram cannot be reached/whatever|false| -|`KOYOTE_REDIS_CHECK_UNSENDED_EVENTS_INTEVAL`|Interval (in seconds) to check for unsent Telegram events|empty| -|`KOYOTE_REDIS_UNSENDED_TASK_TTL`|Time in seconds for unsent Telegram events to expire|empty| -|`KOYOTE_REDIS_INSTANCE_URI`|Redis instance host|empty| -|`KOYOTE_REDIS_INSTANCE_PORT`|Redis instance port|empty| -|`KOYOTE_REDIS_USERNAME`|Redis username (default 'root')|empty| -|`KOYOTE_REDIS_PASSWORD`|Redis password|empty| # GitLab configuration 1. Open your project in GitLab and go to Settings -> Webhooks 2. Check the triggers that you want to receive in Telegram -3. Insert the URL (e.g. `http://koyote/notify/`) +3. Insert the URL (e.g. `http://koyote/notify//`) (topic_id optional field if you are using Telegram Topics) 4. Press the "Add Webhook" button at the bottom of the page 5. At the bottom of the page, you can see the new webhook. Try sending a test event with the "Test" button and select the event you want to receive diff --git a/go.mod b/go.mod index 0e6593f..0d1bc20 100644 --- a/go.mod +++ b/go.mod @@ -1,30 +1,35 @@ module github.com/koyote -go 1.19 +go 1.21.5 require ( - github.com/avast/retry-go/v4 v4.3.0 github.com/caarlos0/env/v6 v6.10.1 - github.com/go-redis/redis/v8 v8.11.5 - github.com/gookit/slog v0.3.3 - github.com/gorilla/mux v1.8.0 - github.com/mymmrac/telego v0.16.1 + github.com/gookit/slog v0.5.5 + github.com/gorilla/mux v1.8.1 + github.com/mymmrac/telego v0.29.1 github.com/pkg/errors v0.9.1 ) require ( - github.com/andybalholm/brotli v1.0.4 // indirect - github.com/cespare/xxhash/v2 v2.1.2 // indirect - github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect - github.com/fasthttp/router v1.4.11 // indirect - github.com/goccy/go-json v0.9.11 // indirect - github.com/gookit/color v1.5.1 // indirect - github.com/gookit/goutil v0.5.4 // indirect - github.com/gookit/gsr v0.0.7 // indirect - github.com/klauspost/compress v1.15.0 // indirect - github.com/savsgio/gotils v0.0.0-20220530130905-52f3993e8d6d // indirect + github.com/andybalholm/brotli v1.1.0 // indirect + github.com/bytedance/sonic v1.10.2 // indirect + github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect + github.com/chenzhuoyu/iasm v0.9.1 // indirect + github.com/fasthttp/router v1.4.22 // indirect + github.com/gookit/color v1.5.4 // indirect + github.com/gookit/goutil v0.6.15 // indirect + github.com/gookit/gsr v0.1.0 // indirect + github.com/grbit/go-json v0.11.0 // indirect + github.com/klauspost/compress v1.17.6 // indirect + github.com/klauspost/cpuid/v2 v2.2.6 // indirect + github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee // indirect + github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect - github.com/valyala/fasthttp v1.39.0 // indirect - github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 // indirect - golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a // indirect + github.com/valyala/fasthttp v1.52.0 // indirect + github.com/valyala/fastjson v1.6.4 // indirect + github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect + golang.org/x/arch v0.6.0 // indirect + golang.org/x/sync v0.5.0 // indirect + golang.org/x/sys v0.17.0 // indirect + golang.org/x/text v0.14.0 // indirect ) diff --git a/go.sum b/go.sum index 0f4c30f..d56fbea 100644 --- a/go.sum +++ b/go.sum @@ -1,93 +1,85 @@ -github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY= -github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= -github.com/avast/retry-go/v4 v4.3.0 h1:cqI48aXx0BExKoM7XPklDpoHAg7/srPPLAfWG5z62jo= -github.com/avast/retry-go/v4 v4.3.0/go.mod h1:bqOlT4nxk4phk9buiQFaghzjpqdchOSwPgjdfdQBtdg= +github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= +github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= +github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM= +github.com/bytedance/sonic v1.10.0-rc/go.mod h1:ElCzW+ufi8qKqNW0FY314xriJhyJhuoJ3gFZdAHF7NM= +github.com/bytedance/sonic v1.10.2 h1:GQebETVBxYB7JGWJtLBi07OVzWwt+8dWA00gEVW2ZFE= +github.com/bytedance/sonic v1.10.2/go.mod h1:iZcSUejdk5aukTND/Eu/ivjQuEL0Cu9/rf50Hi0u/g4= github.com/caarlos0/env/v6 v6.10.1 h1:t1mPSxNpei6M5yAeu1qtRdPAK29Nbcf/n3G7x+b3/II= github.com/caarlos0/env/v6 v6.10.1/go.mod h1:hvp/ryKXKipEkcuYjs9mI4bBCg+UI0Yhgm5Zu0ddvwc= -github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= -github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY= +github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk= +github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d h1:77cEq6EriyTZ0g/qfRdp61a3Uu/AWrgIq2s0ClJV1g0= +github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d/go.mod h1:8EPpVsBuRksnlj1mLy4AWzRNQYxauNi62uWcE3to6eA= +github.com/chenzhuoyu/iasm v0.9.0/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog= +github.com/chenzhuoyu/iasm v0.9.1 h1:tUHQJXo3NhBqw6s33wkGn9SP3bvrWLdlVIJ3hQBL7P0= +github.com/chenzhuoyu/iasm v0.9.1/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog= 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 h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= -github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= -github.com/fasthttp/router v1.4.11 h1:99BvgVxeS2oOZBHnKr/okpdPq1jkn8WvYA2trh/71LY= -github.com/fasthttp/router v1.4.11/go.mod h1:luEEYkGBSAmYyPaMeIUGNgqY+FdHHYDOK9Kivaw7aNo= -github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= -github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI= -github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo= -github.com/goccy/go-json v0.9.11 h1:/pAaQDLHEoCq/5FFmSKBswWmK6H0e8g4159Kc/X/nqk= -github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= -github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/gookit/color v1.5.1 h1:Vjg2VEcdHpwq+oY63s/ksHrgJYCTo0bwWvmmYWdE9fQ= -github.com/gookit/color v1.5.1/go.mod h1:wZFzea4X8qN6vHOSP2apMb4/+w/orMznEzYsIHPaqKM= -github.com/gookit/goutil v0.5.4 h1:SUorRYjdeNyAP0f4w0VDh4J6N3V72j0Iium6fP+xhb4= -github.com/gookit/goutil v0.5.4/go.mod h1:NQJY4PEwCCW27s4bIxjEJQbsPnsxVhQqRF2xU6L3Qrk= -github.com/gookit/gsr v0.0.7 h1:xtxVOkCq3KVBt9+koMSvpr7cVMnlKDsqO7gI5f7OTEE= -github.com/gookit/gsr v0.0.7/go.mod h1:Q3CLTuluDDyk9/Du6xM721lG9/LQ3ywZde9bjmHyWA8= -github.com/gookit/slog v0.3.3 h1:zCd+XhbKXXDhtrtlNVuDuFLDm1K4MEY9LbmR6WYf4hE= -github.com/gookit/slog v0.3.3/go.mod h1:KA7s4YyTXWnW1914+7Nk4I0Txp8m2OlUnOpiY5xT4Yk= -github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= -github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= -github.com/klauspost/compress v1.15.0 h1:xqfchp4whNFxn5A4XFyyYtitiWI8Hy5EW59jEwcyL6U= -github.com/klauspost/compress v1.15.0/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= -github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mymmrac/telego v0.16.1 h1:MMGW7CcyRtSmCH8EJf5mX+S9KemXFUuYD6h1W+8KU5U= -github.com/mymmrac/telego v0.16.1/go.mod h1:SNwAJI5rkdBvma9WzbYo/jjrfCg8yzoFicBdyHLCW4s= -github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= -github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= -github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE= +github.com/fasthttp/router v1.4.22 h1:qwWcYBbndVDwts4dKaz+A2ehsnbKilmiP6pUhXBfYKo= +github.com/fasthttp/router v1.4.22/go.mod h1:KeMvHLqhlB9vyDWD5TSvTccl9qeWrjSSiTJrJALHKV0= +github.com/gookit/color v1.5.4 h1:FZmqs7XOyGgCAxmWyPslpiok1k05wmY3SJTytgvYFs0= +github.com/gookit/color v1.5.4/go.mod h1:pZJOeOS8DM43rXbp4AZo1n9zCU2qjpcRko0b6/QJi9w= +github.com/gookit/goutil v0.6.15 h1:mMQ0ElojNZoyPD0eVROk5QXJPh2uKR4g06slgPDF5Jo= +github.com/gookit/goutil v0.6.15/go.mod h1:qdKdYEHQdEtyH+4fNdQNZfJHhI0jUZzHxQVAV3DaMDY= +github.com/gookit/gsr v0.1.0 h1:0gadWaYGU4phMs0bma38t+Do5OZowRMEVlHv31p0Zig= +github.com/gookit/gsr v0.1.0/go.mod h1:7wv4Y4WCnil8+DlDYHBjidzrEzfHhXEoFjEA0pPPWpI= +github.com/gookit/slog v0.5.5 h1:XoyK3NilKzuC/umvnqTQDHTOnpC8R6pvlr/ht9PyfgU= +github.com/gookit/slog v0.5.5/go.mod h1:RfIwzoaQ8wZbKdcqG7+3EzbkMqcp2TUn3mcaSZAw2EQ= +github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= +github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= +github.com/grbit/go-json v0.11.0 h1:bAbyMdYrYl/OjYsSqLH99N2DyQ291mHy726Mx+sYrnc= +github.com/grbit/go-json v0.11.0/go.mod h1:IYpHsdybQ386+6g3VE6AXQ3uTGa5mquBme5/ZWmtzek= +github.com/klauspost/compress v1.17.6 h1:60eq2E/jlfwQXtvZEeBUYADs+BwKBWURIY+Gj2eRGjI= +github.com/klauspost/compress v1.17.6/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= +github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/klauspost/cpuid/v2 v2.2.6 h1:ndNyv040zDGIDh8thGkXYjnFtiN02M1PVVF+JE/48xc= +github.com/klauspost/cpuid/v2 v2.2.6/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= +github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= +github.com/mymmrac/telego v0.29.1 h1:nsNnK0mS18OL+unoDjDI6BVfafJBbT8Wtj7rCzEWoM8= +github.com/mymmrac/telego v0.29.1/go.mod h1:ZLD1+L2TQRr97NPOCoN1V2w8y9kmFov33OfZ3qT8cF4= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/savsgio/gotils v0.0.0-20220530130905-52f3993e8d6d h1:Q+gqLBOPkFGHyCJxXMRqtUgUbTjI8/Ze8vu8GGyNFwo= -github.com/savsgio/gotils v0.0.0-20220530130905-52f3993e8d6d/go.mod h1:Gy+0tqhJvgGlqnTF8CVGP0AaGRjwBtXs/a5PA0Y3+A4= +github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee h1:8Iv5m6xEo1NR1AvpV+7XmhI4r39LGNzwUL4YpMuL5vk= +github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee/go.mod h1:qwtSXrKuJh/zsFQ12yEE89xfCrGKK63Rr7ctU/uCo4g= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= -github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= +github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= -github.com/valyala/fasthttp v1.38.0/go.mod h1:t/G+3rLek+CyY9bnIE+YlMRddxVAAGjhxndDB4i4C0I= -github.com/valyala/fasthttp v1.39.0 h1:lW8mGeM7yydOqZKmwyMTaz/PH/A+CLgtmmcjv+OORfU= -github.com/valyala/fasthttp v1.39.0/go.mod h1:t/G+3rLek+CyY9bnIE+YlMRddxVAAGjhxndDB4i4C0I= -github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= -github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 h1:QldyIu/L63oPpyvQmHgvgickp1Yw510KJOqX7H24mg8= -github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220225172249-27dd8689420f h1:oA4XRj0qtSt8Yo1Zms0CUlsT3KG69V2UGQWPBxujDmc= -golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +github.com/valyala/fasthttp v1.52.0 h1:wqBQpxH71XW0e2g+Og4dzQM8pk34aFYlA1Ga8db7gU0= +github.com/valyala/fasthttp v1.52.0/go.mod h1:hf5C4QnVMkNXMspnsUlfM3WitlgYflyhHYoKol/szxQ= +github.com/valyala/fastjson v1.6.4 h1:uAUNq9Z6ymTgGhcm0UynUAB6tlbakBrz6CQFax3BXVQ= +github.com/valyala/fastjson v1.6.4/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY= +github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no= +github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM= +go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU= +go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= +golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= +golang.org/x/arch v0.6.0 h1:S0JTfE48HbRj80+4tbvZDYsJ3tGv6BUU3XxyZ7CirAc= +golang.org/x/arch v0.6.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= +golang.org/x/exp v0.0.0-20220909182711-5c715a9e8561 h1:MDc5xs78ZrZr3HMQugiXOAkSZtfTpbJLDr/lwfgO53E= +golang.org/x/exp v0.0.0-20220909182711-5c715a9e8561/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE= +golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= +golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50= +rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= diff --git a/main.go b/main.go index 11999a5..73d5e85 100644 --- a/main.go +++ b/main.go @@ -3,15 +3,11 @@ package main import ( "github.com/koyote/pkg/api" "github.com/koyote/pkg/config" - "github.com/koyote/pkg/redis" "github.com/koyote/pkg/telegram" ) func main() { config.LoadConfig() - if config.GlobalAppConfig.Redis.Enabled { - go redis.ConnectToRedis() - } go telegram.StartBot() api.StartPolling() } diff --git a/pkg/api/api.go b/pkg/api/api.go index e1c1d92..b944c2b 100644 --- a/pkg/api/api.go +++ b/pkg/api/api.go @@ -16,6 +16,7 @@ func returnError(w http.ResponseWriter, r *http.Request) { } func receiveEventJSON(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/json") vars := mux.Vars(r) body, err := ioutil.ReadAll(r.Body) @@ -23,7 +24,7 @@ func receiveEventJSON(w http.ResponseWriter, r *http.Request) { log.Error("Error while read payload from request to Koyote. Error: ", err) } - err = events.EventMatcher(body, vars["chat_id"]) + err = events.EventMatcher(body, vars["chat_id"], vars["thread_id"]) if err != nil { http.Error(w, fmt.Sprint("Error while compare Event to template. Error: ", err), http.StatusBadRequest) } @@ -32,6 +33,7 @@ func receiveEventJSON(w http.ResponseWriter, r *http.Request) { func StartPolling() { router := mux.NewRouter().StrictSlash(true) router.HandleFunc("/notify/{chat_id}", receiveEventJSON).Methods("POST") + router.HandleFunc("/notify/{chat_id}/{thread_id}", receiveEventJSON).Methods("POST") router.HandleFunc("/notify", returnError) log.Info("Starting API on port", config.GlobalAppConfig.Global.ListenPort) diff --git a/pkg/config/config.go b/pkg/config/config.go index 2c1ac46..a63093a 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -18,17 +18,6 @@ type ApplicationConfig struct { Push bool `env:"KOYOTE_ENABLE_PUSH_NOTIFICATION"` TagPush bool `env:"KOYOTE_ENABLE_TAG_PUSH_NOTIFICATION"` } - Redis struct { - Enabled bool `env:"KOYOTE_REDIS_ENABLED"` - CheckUnsendedEventsInterval int `env:"KOYOTE_REDIS_CHECK_UNSENDED_EVENTS_INTEVAL,unset"` - UnsendendTaskTTL int `env:"KOYOTE_REDIS_UNSENDED_TASK_TTL,unset"` - Host string `env:"KOYOTE_REDIS_INSTANCE_URI,unset"` - Port string `env:"KOYOTE_REDIS_INSTANCE_PORT,unset"` - Auth struct { - Username string `env:"KOYOTE_REDIS_USERNAME,unset"` - Password string `env:"KOYOTE_REDIS_PASSWORD,unset"` - } - } } var GlobalAppConfig ApplicationConfig diff --git a/pkg/events/events.go b/pkg/events/events.go index a312936..ed617a8 100644 --- a/pkg/events/events.go +++ b/pkg/events/events.go @@ -4,9 +4,6 @@ import ( "encoding/json" "fmt" - log "github.com/gookit/slog" - "github.com/koyote/pkg/config" - "github.com/koyote/pkg/redis" "github.com/koyote/pkg/telegram" "github.com/pkg/errors" ) @@ -60,7 +57,7 @@ func (e GitlabPushEvent) TemplateMessage() (string, error) { return result, nil } -func EventMatcher(eventJSON []byte, chatID string) error { +func EventMatcher(eventJSON []byte, chatID, threadID string) error { var receivedEventType GitlabEventTypeDetector err := json.Unmarshal(eventJSON, &receivedEventType) if err != nil { @@ -77,12 +74,14 @@ func EventMatcher(eventJSON []byte, chatID string) error { return errors.Wrap(err, "Error while templating message!") } - err = telegram.SendEventMessage(chatID, eventMessage) - if err != nil && config.GlobalAppConfig.Redis.Enabled { - redis.PublishEventToRedisChannel(fmt.Sprintf("chatID:%v|message:%v", chatID, eventMessage)) - log.Warn("Error while send event to Telegram. Trying to save in Redis") - } else if err != nil { - return errors.Wrap(err, "Error while send event to Telegram and Redis was disabled. Event may be lost :( ") + if threadID == "" { + err = telegram.SendEventMessage(chatID, eventMessage) + } else { + err = telegram.SendEventMessageToThread(chatID, threadID, eventMessage) + } + + if err != nil { + return errors.Wrap(err, "Error while send event to Telegram. Event may be lost :( ") } return nil diff --git a/pkg/redis/redis.go b/pkg/redis/redis.go deleted file mode 100644 index 4469c9f..0000000 --- a/pkg/redis/redis.go +++ /dev/null @@ -1,63 +0,0 @@ -package redis - -import ( - "context" - "fmt" - "strings" - "time" - - "github.com/avast/retry-go/v4" - "github.com/go-redis/redis/v8" - log "github.com/gookit/slog" - "github.com/koyote/pkg/config" - "github.com/koyote/pkg/telegram" -) - -var ctx = context.Background() -var redisClient *redis.Client - -func ConnectToRedis() { - redisClient = redis.NewClient(&redis.Options{ - Addr: fmt.Sprintf("%v:%v", config.GlobalAppConfig.Redis.Host, config.GlobalAppConfig.Redis.Port), - Password: config.GlobalAppConfig.Redis.Auth.Password, - DB: 0, - }) - - err := redisClient.Set(ctx, "check", "connection", 5*time.Second).Err() - if err != nil { - log.Fatal("Error while connect to redis. Error: ", err) - } - - sub := redisClient.Subscribe(ctx, "events") - defer sub.Close() - - log.Info("Redis connection established! Subscribed for EVENTS channel!") - ch := sub.Channel() - - for msg := range ch { - log.Info("Received Event message from Redis. Trying to resend it to Telegram") - ResendMessageToTelegram(msg) - } - -} - -func PublishEventToRedisChannel(message string) { - log.Info("Saving received event to Redis") - redisClient.Publish(ctx, "events", message) -} - -func ResendMessageToTelegram(msg *redis.Message) { - eventMessage := strings.SplitAfter(msg.Payload, "|") - chatID := strings.ReplaceAll(strings.ReplaceAll(eventMessage[0], "|", ""), "chatID:", "") - message := strings.Replace(eventMessage[1], "message:", "", 1) - - err := retry.Do( - func() error { - err := telegram.SendEventMessage(chatID, message) - return err - }) - if err != nil { - log.Error("Resending message failed. Event probably lost!") - } - -} diff --git a/pkg/telegram/bot.go b/pkg/telegram/bot.go index cf33a58..888fdb4 100644 --- a/pkg/telegram/bot.go +++ b/pkg/telegram/bot.go @@ -1,11 +1,13 @@ package telegram import ( + "fmt" "strconv" log "github.com/gookit/slog" "github.com/koyote/pkg/config" "github.com/mymmrac/telego" + th "github.com/mymmrac/telego/telegohandler" "github.com/pkg/errors" ) @@ -22,8 +24,81 @@ func StartBot() { log.Info("Telegram bot started!") Bot = bot // Start Polling - _, _ = bot.UpdatesViaLongPulling(nil) - defer bot.StopLongPulling() + updates, _ := bot.UpdatesViaLongPolling(nil) + defer bot.StopLongPolling() + + // Create bot handler and specify from where to get updates + bh, _ := th.NewBotHandler(bot, updates) + + // Stop handling updates + defer bh.Stop() + + bh.Handle(func(bot *telego.Bot, update telego.Update) { + _, _ = bot.SendMessage( + &telego.SendMessageParams{ + ChatID: update.Message.Chat.ChatID(), + Text: fmt.Sprintf("Hello %s! Use /help command to get available commands!", update.Message.From.FirstName), + ParseMode: "HTML", + LinkPreviewOptions: &telego.LinkPreviewOptions{IsDisabled: true}, + ReplyParameters: &telego.ReplyParameters{MessageID: update.Message.MessageID}, + }, + ) + }, th.CommandEqual("start")) + + bh.Handle(func(bot *telego.Bot, update telego.Update) { + _, _ = bot.SendMessage( + &telego.SendMessageParams{ + ChatID: update.Message.Chat.ChatID(), + Text: fmt.Sprintf(` + Hello %s! Have a look on supported commands: + + /chatID - Return current chatID + /threadID - Return current threadID (If 0 then you are in General Thread or chat without Threads support)`, update.Message.From.FirstName), + ParseMode: "HTML", + LinkPreviewOptions: &telego.LinkPreviewOptions{IsDisabled: true}, + ReplyParameters: &telego.ReplyParameters{MessageID: update.Message.MessageID}, + }, + ) + }, th.CommandEqual("help")) + + bh.Handle(func(bot *telego.Bot, update telego.Update) { + _, _ = bot.SendMessage( + &telego.SendMessageParams{ + ChatID: update.Message.Chat.ChatID(), + Text: fmt.Sprintf("Current Thread ID: %v", update.Message.MessageThreadID), + ParseMode: "HTML", + LinkPreviewOptions: &telego.LinkPreviewOptions{IsDisabled: true}, + ReplyParameters: &telego.ReplyParameters{MessageID: update.Message.MessageID}, + }, + ) + }, th.CommandEqual("threadID")) + + bh.Handle(func(bot *telego.Bot, update telego.Update) { + _, _ = bot.SendMessage( + &telego.SendMessageParams{ + ChatID: update.Message.Chat.ChatID(), + Text: fmt.Sprintf("Current chat ID: %v", update.Message.Chat.ID), + ParseMode: "HTML", + LinkPreviewOptions: &telego.LinkPreviewOptions{IsDisabled: true}, + ReplyParameters: &telego.ReplyParameters{MessageID: update.Message.MessageID}, + }, + ) + }, th.CommandEqual("chatID")) + + bh.Handle(func(bot *telego.Bot, update telego.Update) { + _, _ = bot.SendMessage( + &telego.SendMessageParams{ + ChatID: update.Message.Chat.ChatID(), + Text: "Unknown command, use /help to get additional info about commands", + ParseMode: "HTML", + LinkPreviewOptions: &telego.LinkPreviewOptions{IsDisabled: true}, + ReplyParameters: &telego.ReplyParameters{MessageID: update.Message.MessageID}, + }, + ) + }, th.AnyCommand()) + + // Start handling updates + bh.Start() } func SendEventMessage(chatID string, eventMessage string) error { @@ -33,10 +108,34 @@ func SendEventMessage(chatID string, eventMessage string) error { } _, err = Bot.SendMessage( &telego.SendMessageParams{ - ChatID: telego.ChatID{ID: int64(chatIDInt)}, - Text: eventMessage, - ParseMode: "HTML", - DisableWebPagePreview: true, + ChatID: telego.ChatID{ID: int64(chatIDInt)}, + Text: eventMessage, + ParseMode: "HTML", + LinkPreviewOptions: &telego.LinkPreviewOptions{IsDisabled: true}, + }, + ) + + return errors.Wrap(err, "Error while sending message to Telegram") +} + +func SendEventMessageToThread(chatID, threadID, eventMessage string) error { + chatIDInt, err := strconv.Atoi(chatID) + if err != nil { + return err + } + + threadIDInt, err := strconv.Atoi(threadID) + if err != nil { + return err + } + + _, err = Bot.SendMessage( + &telego.SendMessageParams{ + ChatID: telego.ChatID{ID: int64(chatIDInt)}, + MessageThreadID: int(threadIDInt), + Text: eventMessage, + ParseMode: "HTML", + LinkPreviewOptions: &telego.LinkPreviewOptions{IsDisabled: true}, }, )