mirror of
https://github.com/lukaszraczylo/go-telegram.git
synced 2026-06-05 22:43:59 +00:00
Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 607c3e8ddd | |||
| c9a062ea04 | |||
| 7eb3398396 | |||
| 26b98a5372 | |||
| a416bda5f3 | |||
| 0ee539e991 | |||
| da27421521 | |||
| 728b28b0c5 |
@@ -0,0 +1,17 @@
|
||||
After: static-header-slices + bool-fast-path
|
||||
goos: darwin
|
||||
goarch: arm64
|
||||
pkg: github.com/lukaszraczylo/go-telegram/client
|
||||
cpu: Apple M4 Max
|
||||
BenchmarkCall_BoolResponse-16 4597374 526.3 ns/op 1842 B/op 14 allocs/op
|
||||
BenchmarkCall_StructResponse-16 3740096 679.6 ns/op 1973 B/op 16 allocs/op
|
||||
BenchmarkEncodeJSONBody-16 41997352 58.35 ns/op 96 B/op 2 allocs/op
|
||||
BenchmarkDecodeResult_Bool-16 863273641 2.872 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkDecodeResult_Struct-16 19988096 100.3 ns/op 144 B/op 2 allocs/op
|
||||
|
||||
Deltas vs baseline (allocs/op):
|
||||
Call_BoolResponse: 18 -> 14 (-4)
|
||||
Call_StructResponse: 18 -> 16 (-2)
|
||||
DecodeResult_Bool: 2 -> 0 (-2, also -94% ns)
|
||||
DecodeResult_Struct: 2 -> 2 (flat)
|
||||
EncodeJSONBody: 2 -> 2 (flat)
|
||||
@@ -0,0 +1,27 @@
|
||||
After: static-headers + bool-fast-path + lazy-Context.Values
|
||||
goos: darwin
|
||||
goarch: arm64
|
||||
cpu: Apple M4 Max
|
||||
|
||||
pkg: github.com/lukaszraczylo/go-telegram/client
|
||||
BenchmarkCall_BoolResponse-16 4597374 526.3 ns/op 1842 B/op 14 allocs/op
|
||||
BenchmarkCall_StructResponse-16 3740096 679.6 ns/op 1973 B/op 16 allocs/op
|
||||
BenchmarkEncodeJSONBody-16 41997352 58.35 ns/op 96 B/op 2 allocs/op
|
||||
BenchmarkDecodeResult_Bool-16 863273641 2.872 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkDecodeResult_Struct-16 19988096 100.3 ns/op 144 B/op 2 allocs/op
|
||||
|
||||
pkg: github.com/lukaszraczylo/go-telegram/dispatch
|
||||
BenchmarkRouter_DispatchCommand-16 14912385 156.4 ns/op 416 B/op 5 allocs/op
|
||||
BenchmarkRouter_DispatchTextRegex-16 12495229 187.7 ns/op 428 B/op 5 allocs/op
|
||||
BenchmarkRouter_DispatchFilter-16 148631502 16.11 ns/op 48 B/op 1 allocs/op
|
||||
BenchmarkRouter_NewContext-16 1000000000 1.608 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkExtractCommand-16 25267845 92.52 ns/op 0 B/op 0 allocs/op
|
||||
|
||||
Cumulative deltas vs baseline:
|
||||
Call_BoolResponse: 18 -> 14 allocs (-4)
|
||||
Call_StructResponse: 18 -> 16 allocs (-2)
|
||||
DecodeResult_Bool: 2 -> 0 allocs (-2, also 50ns -> 2.87ns)
|
||||
DispatchFilter: 2 -> 1 alloc (-1, also 32ns -> 16ns)
|
||||
NewContext: 5.79ns -> 1.61ns (-72%)
|
||||
DispatchCommand: 5 -> 5 allocs (flat — map alloc shifted from NewContext to first Set)
|
||||
DispatchTextRegex: 5 -> 5 allocs (flat — same reason)
|
||||
@@ -0,0 +1,27 @@
|
||||
After: static-headers + bool-fast-path + lazy-Values + typed-fields
|
||||
goos: darwin
|
||||
goarch: arm64
|
||||
cpu: Apple M4 Max
|
||||
|
||||
pkg: github.com/lukaszraczylo/go-telegram/client
|
||||
BenchmarkCall_BoolResponse-16 4597374 526.3 ns/op 1842 B/op 14 allocs/op
|
||||
BenchmarkCall_StructResponse-16 3740096 679.6 ns/op 1973 B/op 16 allocs/op
|
||||
BenchmarkEncodeJSONBody-16 41997352 58.35 ns/op 96 B/op 2 allocs/op
|
||||
BenchmarkDecodeResult_Bool-16 863273641 2.872 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkDecodeResult_Struct-16 19988096 100.3 ns/op 144 B/op 2 allocs/op
|
||||
|
||||
pkg: github.com/lukaszraczylo/go-telegram/dispatch
|
||||
BenchmarkRouter_DispatchCommand-16 34631486 69.19 ns/op 96 B/op 1 allocs/op
|
||||
BenchmarkRouter_DispatchTextRegex-16 23260198 106.6 ns/op 112 B/op 2 allocs/op
|
||||
BenchmarkRouter_DispatchFilter-16 126697654 19.03 ns/op 96 B/op 1 allocs/op
|
||||
BenchmarkRouter_NewContext-16 1000000000 1.600 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkExtractCommand-16 27345622 87.25 ns/op 0 B/op 0 allocs/op
|
||||
|
||||
Cumulative deltas vs baseline (allocs/op):
|
||||
Call_BoolResponse: 18 -> 14 allocs (-4)
|
||||
Call_StructResponse: 18 -> 16 allocs (-2)
|
||||
DecodeResult_Bool: 2 -> 0 allocs (-2, also 50ns -> 2.87ns)
|
||||
DispatchCommand: 5 -> 1 alloc (-4, also 153ns -> 69ns)
|
||||
DispatchTextRegex: 5 -> 2 allocs (-3, also 181ns -> 107ns)
|
||||
DispatchFilter: 2 -> 1 alloc (-1, but +48B from larger Context struct)
|
||||
NewContext: 5.79ns -> 1.60ns (-72%)
|
||||
@@ -0,0 +1,26 @@
|
||||
After: static-headers + bool-fast-path + lazy-Values + typed-fields + resp-buffer-pool
|
||||
goos: darwin
|
||||
goarch: arm64
|
||||
cpu: Apple M4 Max
|
||||
|
||||
pkg: github.com/lukaszraczylo/go-telegram/client
|
||||
BenchmarkCall_BoolResponse-16 4811347 478.7 ns/op 1331 B/op 13 allocs/op
|
||||
BenchmarkCall_StructResponse-16 4038770 591.6 ns/op 1462 B/op 15 allocs/op
|
||||
BenchmarkEncodeJSONBody-16 47025052 51.30 ns/op 96 B/op 2 allocs/op
|
||||
BenchmarkDecodeResult_Bool-16 853161562 2.824 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkDecodeResult_Struct-16 26811634 88.80 ns/op 144 B/op 2 allocs/op
|
||||
|
||||
pkg: github.com/lukaszraczylo/go-telegram/dispatch
|
||||
BenchmarkRouter_DispatchCommand-16 34631486 69.19 ns/op 96 B/op 1 allocs/op
|
||||
BenchmarkRouter_DispatchTextRegex-16 23260198 106.6 ns/op 112 B/op 2 allocs/op
|
||||
BenchmarkRouter_DispatchFilter-16 126697654 19.03 ns/op 96 B/op 1 allocs/op
|
||||
BenchmarkRouter_NewContext-16 1000000000 1.600 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkExtractCommand-16 27345622 87.25 ns/op 0 B/op 0 allocs/op
|
||||
|
||||
Cumulative deltas vs baseline:
|
||||
Call_BoolResponse: 634ns / 18 allocs / 1957B -> 479ns / 13 allocs / 1331B (-24% / -5 / -626B)
|
||||
Call_StructResponse: 665ns / 18 allocs / 2005B -> 592ns / 15 allocs / 1462B (-11% / -3 / -543B)
|
||||
DecodeResult_Bool: 50ns / 2 allocs / 80B -> 2.8ns / 0 allocs / 0B
|
||||
DispatchCommand: 153ns / 5 allocs / 416B -> 69ns / 1 alloc / 96B (-55% / -4 / -320B)
|
||||
DispatchTextRegex: 181ns / 5 allocs / 428B -> 107ns / 2 allocs / 112B (-41% / -3 / -316B)
|
||||
DispatchFilter: 32ns / 2 allocs / 96B -> 19ns / 1 alloc / 96B (-41% / -1)
|
||||
@@ -0,0 +1,30 @@
|
||||
After: static-headers + bool-fast-path + lazy-Values + typed-fields + resp-buffer-pool + webhook-pool
|
||||
goos: darwin
|
||||
goarch: arm64
|
||||
cpu: Apple M4 Max
|
||||
|
||||
pkg: github.com/lukaszraczylo/go-telegram/client
|
||||
BenchmarkCall_BoolResponse-16 4811347 478.7 ns/op 1331 B/op 13 allocs/op
|
||||
BenchmarkCall_StructResponse-16 4038770 591.6 ns/op 1462 B/op 15 allocs/op
|
||||
BenchmarkEncodeJSONBody-16 47025052 51.30 ns/op 96 B/op 2 allocs/op
|
||||
BenchmarkDecodeResult_Bool-16 853161562 2.824 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkDecodeResult_Struct-16 26811634 88.80 ns/op 144 B/op 2 allocs/op
|
||||
|
||||
pkg: github.com/lukaszraczylo/go-telegram/transport
|
||||
BenchmarkWebhook_ServeHTTP-16 1204390 2020 ns/op 7648 B/op 23 allocs/op
|
||||
|
||||
pkg: github.com/lukaszraczylo/go-telegram/dispatch
|
||||
BenchmarkRouter_DispatchCommand-16 34631486 69.19 ns/op 96 B/op 1 allocs/op
|
||||
BenchmarkRouter_DispatchTextRegex-16 23260198 106.6 ns/op 112 B/op 2 allocs/op
|
||||
BenchmarkRouter_DispatchFilter-16 126697654 19.03 ns/op 96 B/op 1 allocs/op
|
||||
BenchmarkRouter_NewContext-16 1000000000 1.600 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkExtractCommand-16 27345622 87.25 ns/op 0 B/op 0 allocs/op
|
||||
|
||||
Cumulative deltas vs baseline:
|
||||
Call_BoolResponse: 634ns / 18 allocs / 1957B -> 479ns / 13 / 1331B (-24% / -5 / -626B)
|
||||
Call_StructResponse: 665ns / 18 allocs / 2005B -> 592ns / 15 / 1462B (-11% / -3 / -543B)
|
||||
DecodeResult_Bool: 50ns / 2 allocs / 80B -> 2.8ns / 0 / 0B
|
||||
Webhook_ServeHTTP: 2564ns / 24 allocs / 12707B -> 2020ns / 23 / 7648B (-21% / -1 / -5059B)
|
||||
DispatchCommand: 153ns / 5 allocs / 416B -> 69ns / 1 / 96B (-55% / -4 / -320B)
|
||||
DispatchTextRegex: 181ns / 5 allocs / 428B -> 107ns / 2 / 112B (-41% / -3 / -316B)
|
||||
DispatchFilter: 32ns / 2 allocs / 96B -> 19ns / 1 / 96B (-41% / -1)
|
||||
@@ -0,0 +1,19 @@
|
||||
goos: darwin
|
||||
goarch: arm64
|
||||
pkg: github.com/lukaszraczylo/go-telegram/client
|
||||
cpu: Apple M4 Max
|
||||
BenchmarkCall_BoolResponse-16 1875306 633.9 ns/op 1957 B/op 18 allocs/op
|
||||
BenchmarkCall_StructResponse-16 1805024 665.2 ns/op 2005 B/op 18 allocs/op
|
||||
BenchmarkEncodeJSONBody-16 23345811 51.55 ns/op 96 B/op 2 allocs/op
|
||||
BenchmarkDecodeResult_Bool-16 23832240 50.37 ns/op 80 B/op 2 allocs/op
|
||||
BenchmarkDecodeResult_Struct-16 13511192 92.64 ns/op 144 B/op 2 allocs/op
|
||||
|
||||
pkg: github.com/lukaszraczylo/go-telegram/transport
|
||||
BenchmarkWebhook_ServeHTTP-16 465798 2564 ns/op 12707 B/op 24 allocs/op
|
||||
|
||||
pkg: github.com/lukaszraczylo/go-telegram/dispatch
|
||||
BenchmarkRouter_DispatchCommand-16 7303522 152.7 ns/op 416 B/op 5 allocs/op
|
||||
BenchmarkRouter_DispatchTextRegex-16 6740305 180.5 ns/op 428 B/op 5 allocs/op
|
||||
BenchmarkRouter_DispatchFilter-16 39479149 32.18 ns/op 96 B/op 2 allocs/op
|
||||
BenchmarkRouter_NewContext-16 208260764 5.790 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkExtractCommand-16 12988816 92.69 ns/op 0 B/op 0 allocs/op
|
||||
@@ -24,6 +24,9 @@ coverage.html
|
||||
.env
|
||||
.env.local
|
||||
|
||||
# Superpowers brainstorm/spec scratch — never commit
|
||||
docs/superpowers/
|
||||
|
||||
# Stray binaries at repo root from `go build ./cmd/...` or `go run` artefacts.
|
||||
# Listed explicitly (not via /* glob) so source dirs are never accidentally ignored.
|
||||
/echo
|
||||
|
||||
@@ -317,6 +317,24 @@ r.OnCommand("/cmd", named.Handler())
|
||||
|
||||
</details>
|
||||
|
||||
## Benchmarks
|
||||
|
||||
Apples-to-apples micro-benchmarks against the five most-starred Go Telegram libraries (`go-telegram-bot-api`, `telebot.v3`, `go-telegram/bot`, `telego`, `echotron`) live under [`test/benchmarks/`](test/benchmarks/) as a separate Go module.
|
||||
|
||||
<details>
|
||||
<summary>Results — Apple M4 Max · darwin/arm64 · go1.26.2</summary>
|
||||
|
||||
| Path | Fastest | Our position |
|
||||
|------|---------|--------------|
|
||||
| Webhook decode (small Update) | **ours** — 1.74 µs / 11 allocs | 1st of 6 |
|
||||
| Large Update unmarshal (unions + reply markup) | **ours** — 6.67 µs / 34 allocs | 1st of 6 |
|
||||
| `sendMessage` round-trip (mock server) | telego — 36.3 µs / 48 allocs | 2nd of 5 |
|
||||
| Dispatcher routing (20 handlers, last matches) | **ours** — 101 ns / 3 allocs | 1st of 3 |
|
||||
|
||||
Full tables, caveats, and reproduction steps: **[`docs/benchmarks/2026-05-10-comparison.md`](docs/benchmarks/2026-05-10-comparison.md)**.
|
||||
|
||||
</details>
|
||||
|
||||
## Keeping up with Telegram
|
||||
|
||||
When Telegram ships a new Bot API version, regenerating the whole library is one command:
|
||||
|
||||
+51
-7
@@ -8,8 +8,36 @@ import (
|
||||
"io"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var (
|
||||
headerJSONValue = []string{"application/json"}
|
||||
rawOKTrueBody = []byte(`{"ok":true,"result":true}`)
|
||||
rawOKFalseBody = []byte(`{"ok":true,"result":false}`)
|
||||
|
||||
// respBufPool reuses *bytes.Buffer for response body reads. Used on
|
||||
// paths whose decoder copies strings out of the input (decodeResult,
|
||||
// which delegates to goccy/go-json), so the buffer can be returned to
|
||||
// the pool as soon as Unmarshal has run. CallRaw and callMultipartRaw
|
||||
// return slices that alias the buffer and therefore cannot use the
|
||||
// pool without an extra copy that would defeat the point.
|
||||
respBufPool = sync.Pool{New: func() any { return new(bytes.Buffer) }}
|
||||
)
|
||||
|
||||
// maxPooledBufCap caps the buffer size returned to respBufPool. Buffers
|
||||
// larger than this are dropped on the floor so a single huge response
|
||||
// (e.g. a large getFile metadata payload) doesn't bloat the pool for the
|
||||
// rest of the process lifetime.
|
||||
const maxPooledBufCap = 64 * 1024
|
||||
|
||||
func putRespBuf(buf *bytes.Buffer) {
|
||||
if buf.Cap() > maxPooledBufCap {
|
||||
return
|
||||
}
|
||||
respBufPool.Put(buf)
|
||||
}
|
||||
|
||||
// Call is the single point through which every Telegram Bot API method
|
||||
// invocation flows. It marshals the request, signs the URL with the bot
|
||||
// token, dispatches via HTTPDoer, decodes the Result envelope, and
|
||||
@@ -44,8 +72,8 @@ func Call[Req any, Resp any](ctx context.Context, b *Bot, method string, req Req
|
||||
if err != nil {
|
||||
return zero, &NetworkError{Err: err}
|
||||
}
|
||||
httpReq.Header.Set("Content-Type", "application/json")
|
||||
httpReq.Header.Set("Accept", "application/json")
|
||||
httpReq.Header["Content-Type"] = headerJSONValue
|
||||
httpReq.Header["Accept"] = headerJSONValue
|
||||
|
||||
resp, err := b.http.Do(httpReq)
|
||||
if err != nil {
|
||||
@@ -57,12 +85,14 @@ func Call[Req any, Resp any](ctx context.Context, b *Bot, method string, req Req
|
||||
}
|
||||
defer func() { _ = resp.Body.Close() }()
|
||||
|
||||
raw, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
buf := respBufPool.Get().(*bytes.Buffer)
|
||||
buf.Reset()
|
||||
defer putRespBuf(buf)
|
||||
if _, err := buf.ReadFrom(resp.Body); err != nil {
|
||||
return zero, &NetworkError{Err: err}
|
||||
}
|
||||
|
||||
return decodeResult[Resp](b.codec, raw)
|
||||
return decodeResult[Resp](b.codec, buf.Bytes())
|
||||
}
|
||||
|
||||
// CallRaw is like Call but returns the raw JSON of the result field
|
||||
@@ -91,8 +121,8 @@ func CallRaw[Req any](ctx context.Context, b *Bot, method string, req Req) (json
|
||||
if err != nil {
|
||||
return nil, &NetworkError{Err: err}
|
||||
}
|
||||
httpReq.Header.Set("Content-Type", "application/json")
|
||||
httpReq.Header.Set("Accept", "application/json")
|
||||
httpReq.Header["Content-Type"] = headerJSONValue
|
||||
httpReq.Header["Accept"] = headerJSONValue
|
||||
|
||||
resp, err := b.http.Do(httpReq)
|
||||
if err != nil {
|
||||
@@ -139,8 +169,22 @@ func encodeJSONBody(codec Codec, req any) (io.Reader, error) {
|
||||
|
||||
// decodeResult unmarshals raw into Result[Resp] and translates non-OK
|
||||
// responses into *APIError.
|
||||
//
|
||||
// Bool fast path: ~60% of Telegram methods return bool. The Telegram API
|
||||
// emits the result envelope with no whitespace, so a byte-equality check
|
||||
// against the two canonical bodies skips the generic Unmarshal entirely.
|
||||
// Anything that doesn't match exactly (e.g. responses with extra fields,
|
||||
// errors) falls through to the slow path.
|
||||
func decodeResult[Resp any](codec Codec, raw []byte) (Resp, error) {
|
||||
var zero Resp
|
||||
if _, isBool := any(zero).(bool); isBool {
|
||||
switch {
|
||||
case bytes.Equal(raw, rawOKTrueBody):
|
||||
return any(true).(Resp), nil
|
||||
case bytes.Equal(raw, rawOKFalseBody):
|
||||
return any(false).(Resp), nil
|
||||
}
|
||||
}
|
||||
var env Result[Resp]
|
||||
if err := codec.Unmarshal(raw, &env); err != nil {
|
||||
return zero, &ParseError{Err: err, Body: copyBody(raw)}
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"io"
|
||||
"net/http"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// stubDoer returns the same canned response body for every request. It
|
||||
// is intentionally minimal — testify mock has its own overhead that
|
||||
// would dominate the per-call cost we want to measure.
|
||||
type stubDoer struct{ body []byte }
|
||||
|
||||
func (s *stubDoer) Do(_ *http.Request) (*http.Response, error) {
|
||||
return &http.Response{
|
||||
StatusCode: http.StatusOK,
|
||||
Body: io.NopCloser(bytes.NewReader(s.body)),
|
||||
Header: http.Header{},
|
||||
}, nil
|
||||
}
|
||||
|
||||
type benchSendReq struct {
|
||||
ChatID int64 `json:"chat_id"`
|
||||
Text string `json:"text"`
|
||||
}
|
||||
|
||||
type benchMsgResp struct {
|
||||
MessageID int64 `json:"message_id"`
|
||||
Date int64 `json:"date"`
|
||||
Text string `json:"text"`
|
||||
}
|
||||
|
||||
func BenchmarkCall_BoolResponse(b *testing.B) {
|
||||
d := &stubDoer{body: []byte(`{"ok":true,"result":true}`)}
|
||||
bot := New("123:abc", WithHTTPClient(d))
|
||||
ctx := context.Background()
|
||||
req := &benchSendReq{ChatID: 42, Text: "hi"}
|
||||
b.ReportAllocs()
|
||||
for b.Loop() {
|
||||
if _, err := Call[*benchSendReq, bool](ctx, bot, "setMyCommands", req); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkCall_StructResponse(b *testing.B) {
|
||||
d := &stubDoer{body: []byte(`{"ok":true,"result":{"message_id":1,"date":0,"text":"ok"}}`)}
|
||||
bot := New("123:abc", WithHTTPClient(d))
|
||||
ctx := context.Background()
|
||||
req := &benchSendReq{ChatID: 42, Text: "hi"}
|
||||
b.ReportAllocs()
|
||||
for b.Loop() {
|
||||
if _, err := Call[*benchSendReq, benchMsgResp](ctx, bot, "sendMessage", req); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkEncodeJSONBody(b *testing.B) {
|
||||
codec := DefaultCodec{}
|
||||
req := &benchSendReq{ChatID: 42, Text: "hello, world"}
|
||||
b.ReportAllocs()
|
||||
for b.Loop() {
|
||||
r, err := encodeJSONBody(codec, req)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
_ = r
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkDecodeResult_Bool(b *testing.B) {
|
||||
codec := DefaultCodec{}
|
||||
raw := []byte(`{"ok":true,"result":true}`)
|
||||
b.ReportAllocs()
|
||||
for b.Loop() {
|
||||
if _, err := decodeResult[bool](codec, raw); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkDecodeResult_Struct(b *testing.B) {
|
||||
codec := DefaultCodec{}
|
||||
raw := []byte(`{"ok":true,"result":{"message_id":1,"date":0,"text":"ok"}}`)
|
||||
b.ReportAllocs()
|
||||
for b.Loop() {
|
||||
if _, err := decodeResult[benchMsgResp](codec, raw); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
+8
-5
@@ -1,6 +1,7 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"github.com/goccy/go-json"
|
||||
"io"
|
||||
@@ -69,7 +70,7 @@ func callMultipart[Resp any](ctx context.Context, b *Bot, method string, mp mult
|
||||
return zero, &NetworkError{Err: err}
|
||||
}
|
||||
req.Header.Set("Content-Type", mw.FormDataContentType())
|
||||
req.Header.Set("Accept", "application/json")
|
||||
req.Header["Accept"] = headerJSONValue
|
||||
|
||||
resp, err := b.http.Do(req)
|
||||
if err != nil {
|
||||
@@ -81,12 +82,14 @@ func callMultipart[Resp any](ctx context.Context, b *Bot, method string, mp mult
|
||||
}
|
||||
defer func() { _ = resp.Body.Close() }()
|
||||
|
||||
raw, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
buf := respBufPool.Get().(*bytes.Buffer)
|
||||
buf.Reset()
|
||||
defer putRespBuf(buf)
|
||||
if _, err := buf.ReadFrom(resp.Body); err != nil {
|
||||
_ = pr.CloseWithError(err)
|
||||
return zero, &NetworkError{Err: err}
|
||||
}
|
||||
return decodeResult[Resp](b.codec, raw)
|
||||
return decodeResult[Resp](b.codec, buf.Bytes())
|
||||
}
|
||||
|
||||
// callMultipartRaw is callMultipart's sibling that returns the raw result
|
||||
@@ -125,7 +128,7 @@ func callMultipartRaw(ctx context.Context, b *Bot, method string, mp multipartRe
|
||||
return nil, &NetworkError{Err: err}
|
||||
}
|
||||
req.Header.Set("Content-Type", mw.FormDataContentType())
|
||||
req.Header.Set("Accept", "application/json")
|
||||
req.Header["Accept"] = headerJSONValue
|
||||
|
||||
resp, err := b.http.Do(req)
|
||||
if err != nil {
|
||||
|
||||
+34
-9
@@ -21,20 +21,45 @@ import (
|
||||
// Update is the raw update; payload-typed handlers also receive a
|
||||
// narrowed pointer to one of its sub-fields.
|
||||
//
|
||||
// Values is a per-update bag matchers populate. Conventional keys:
|
||||
// Command, CommandArgs and RegexMatch are populated by the router for
|
||||
// the matching route kind; they replace the previous "command",
|
||||
// "command_args" and "regex_match" entries in Values, which were the
|
||||
// only conventional keys. Values remains for user-defined custom keys.
|
||||
//
|
||||
// "command": string, the matched bot command (e.g. "/start")
|
||||
// "command_args": string, everything after the command
|
||||
// "regex_match": []string, regex sub-matches when OnText matches
|
||||
// Command is the matched bot command (e.g. "/start"); empty when the
|
||||
// route is not a command match.
|
||||
//
|
||||
// CommandArgs is everything after the command; empty when no command
|
||||
// matched or the command had no trailing text.
|
||||
//
|
||||
// RegexMatch is the regex sub-matches when an OnText/OnCallback regex
|
||||
// route matched; nil otherwise.
|
||||
//
|
||||
// Values is lazily allocated for user-defined keys. Handlers that don't
|
||||
// write pay no allocation. Reads against a nil map return the zero
|
||||
// value. Writers must use Set instead of indexing the map directly.
|
||||
type Context struct {
|
||||
Ctx context.Context
|
||||
Bot *client.Bot
|
||||
Update *api.Update
|
||||
Values map[string]any
|
||||
Ctx context.Context
|
||||
Bot *client.Bot
|
||||
Update *api.Update
|
||||
Command string
|
||||
CommandArgs string
|
||||
RegexMatch []string
|
||||
Values map[string]any
|
||||
}
|
||||
|
||||
// NewContext constructs a Context. Used by Router internally; exposed for
|
||||
// custom test harnesses.
|
||||
func NewContext(ctx context.Context, b *client.Bot, u *api.Update) *Context {
|
||||
return &Context{Ctx: ctx, Bot: b, Update: u, Values: map[string]any{}}
|
||||
return &Context{Ctx: ctx, Bot: b, Update: u}
|
||||
}
|
||||
|
||||
// Set writes key/val into Values, allocating the map on first use. Use
|
||||
// this instead of `c.Values[k] = v` so the no-write path stays
|
||||
// allocation-free.
|
||||
func (c *Context) Set(key string, val any) {
|
||||
if c.Values == nil {
|
||||
c.Values = make(map[string]any, 2)
|
||||
}
|
||||
c.Values[key] = val
|
||||
}
|
||||
|
||||
+3
-3
@@ -138,8 +138,8 @@ func (r *Router) runGroupHandlers(c *Context, m *api.Message, g int) (matched bo
|
||||
if route.group != g || route.cmd != cmd {
|
||||
continue
|
||||
}
|
||||
c.Values["command"] = cmd
|
||||
c.Values["command_args"] = args
|
||||
c.Command = cmd
|
||||
c.CommandArgs = args
|
||||
if err := route.handler(c, m); err != nil {
|
||||
if errors.Is(err, ErrContinueGroups) {
|
||||
continue
|
||||
@@ -159,7 +159,7 @@ func (r *Router) runGroupHandlers(c *Context, m *api.Message, g int) (matched bo
|
||||
if subs == nil {
|
||||
continue
|
||||
}
|
||||
c.Values["regex_match"] = subs
|
||||
c.RegexMatch = subs
|
||||
if err := route.handler(c, m); err != nil {
|
||||
if errors.Is(err, ErrContinueGroups) {
|
||||
continue
|
||||
|
||||
+23
-4
@@ -300,6 +300,25 @@ func (r *Router) OnPurchasedPaidMedia(h Handler[*api.PaidMediaPurchased]) {
|
||||
// serial (legacy) behaviour.
|
||||
//
|
||||
// Run waits for all in-flight handlers to finish before returning.
|
||||
// Process runs a single update through the router's middleware and handler
|
||||
// chain synchronously. Entry point for callers sourcing updates outside the
|
||||
// standard transport.Updater flow — custom webhook frameworks, message-bus
|
||||
// consumers, or tests driving the router without spinning up Run.
|
||||
//
|
||||
// Honours the router's global middleware (Use) but bypasses the concurrency
|
||||
// semaphore wired up by Run; the caller controls parallelism.
|
||||
func (r *Router) Process(ctx context.Context, u *api.Update) error {
|
||||
if u == nil {
|
||||
return nil
|
||||
}
|
||||
root := r.dispatch
|
||||
for i := len(r.globalMW) - 1; i >= 0; i-- {
|
||||
root = r.globalMW[i](root)
|
||||
}
|
||||
c := NewContext(ctx, r.bot, u)
|
||||
return root(c, u)
|
||||
}
|
||||
|
||||
func (r *Router) Run(ctx context.Context, u transport.Updater) error {
|
||||
runErr := make(chan error, 1)
|
||||
go func() { runErr <- u.Run(ctx) }()
|
||||
@@ -467,8 +486,8 @@ func (r *Router) handleMessage(c *Context, m *api.Message) error {
|
||||
if cmd, args, ok := extractCommand(m); ok {
|
||||
for _, route := range r.commands {
|
||||
if route.cmd == cmd {
|
||||
c.Values["command"] = cmd
|
||||
c.Values["command_args"] = args
|
||||
c.Command = cmd
|
||||
c.CommandArgs = args
|
||||
return route.handler(c, m)
|
||||
}
|
||||
}
|
||||
@@ -477,7 +496,7 @@ func (r *Router) handleMessage(c *Context, m *api.Message) error {
|
||||
if m.Text != "" {
|
||||
for _, route := range r.texts {
|
||||
if subs := route.re.FindStringSubmatch(m.Text); subs != nil {
|
||||
c.Values["regex_match"] = subs
|
||||
c.RegexMatch = subs
|
||||
return route.handler(c, m)
|
||||
}
|
||||
}
|
||||
@@ -495,7 +514,7 @@ func (r *Router) handleMessage(c *Context, m *api.Message) error {
|
||||
func (r *Router) handleCallback(c *Context, q *api.CallbackQuery) error {
|
||||
for _, route := range r.callbacks {
|
||||
if subs := route.re.FindStringSubmatch(q.Data); subs != nil {
|
||||
c.Values["regex_match"] = subs
|
||||
c.RegexMatch = subs
|
||||
return route.handler(c, q)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
package dispatch
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/lukaszraczylo/go-telegram/api"
|
||||
"github.com/lukaszraczylo/go-telegram/client"
|
||||
)
|
||||
|
||||
func BenchmarkRouter_DispatchCommand(b *testing.B) {
|
||||
r := New(client.New("t"))
|
||||
r.OnCommand("/start", func(c *Context, m *api.Message) error { return nil })
|
||||
u := cmdMessage("/start hello")
|
||||
ctx := context.Background()
|
||||
b.ReportAllocs()
|
||||
for b.Loop() {
|
||||
c := NewContext(ctx, r.bot, &u)
|
||||
_ = r.dispatch(c, &u)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkRouter_DispatchTextRegex(b *testing.B) {
|
||||
r := New(client.New("t"))
|
||||
r.OnText("^hello.*", func(c *Context, m *api.Message) error { return nil })
|
||||
u := api.Update{
|
||||
UpdateID: 1,
|
||||
Message: &api.Message{
|
||||
MessageID: 1, Date: 0,
|
||||
Chat: api.Chat{ID: 1, Type: api.ChatTypePrivate},
|
||||
Text: "hello world",
|
||||
},
|
||||
}
|
||||
ctx := context.Background()
|
||||
b.ReportAllocs()
|
||||
for b.Loop() {
|
||||
c := NewContext(ctx, r.bot, &u)
|
||||
_ = r.dispatch(c, &u)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkRouter_DispatchFilter(b *testing.B) {
|
||||
r := New(client.New("t"))
|
||||
r.OnMessageFilter(
|
||||
func(m *api.Message) bool { return m != nil && m.Text == "ping" },
|
||||
func(c *Context, m *api.Message) error { return nil },
|
||||
)
|
||||
u := api.Update{
|
||||
UpdateID: 1,
|
||||
Message: &api.Message{
|
||||
MessageID: 1, Date: 0,
|
||||
Chat: api.Chat{ID: 1, Type: api.ChatTypePrivate},
|
||||
Text: "ping",
|
||||
},
|
||||
}
|
||||
ctx := context.Background()
|
||||
b.ReportAllocs()
|
||||
for b.Loop() {
|
||||
c := NewContext(ctx, r.bot, &u)
|
||||
_ = r.dispatch(c, &u)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkRouter_NewContext(b *testing.B) {
|
||||
bot := client.New("t")
|
||||
u := &api.Update{UpdateID: 1}
|
||||
ctx := context.Background()
|
||||
b.ReportAllocs()
|
||||
for b.Loop() {
|
||||
_ = NewContext(ctx, bot, u)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkExtractCommand(b *testing.B) {
|
||||
text := "/start@BotName hello world"
|
||||
cmdLen := len("/start@BotName")
|
||||
m := &api.Message{
|
||||
MessageID: 1, Date: 0,
|
||||
Chat: api.Chat{ID: 1, Type: api.ChatTypePrivate},
|
||||
Text: text,
|
||||
Entities: []api.MessageEntity{
|
||||
{Type: api.MessageEntityTypeBotCommand, Offset: 0, Length: int64(cmdLen)},
|
||||
},
|
||||
}
|
||||
b.ReportAllocs()
|
||||
for b.Loop() {
|
||||
_, _, _ = extractCommand(m)
|
||||
}
|
||||
}
|
||||
+6
-10
@@ -52,7 +52,7 @@ func TestRouter_OnCommandMatches(t *testing.T) {
|
||||
r := New(b)
|
||||
hit := make(chan string, 1)
|
||||
r.OnCommand("/start", func(c *Context, m *api.Message) error {
|
||||
hit <- c.Values["command"].(string)
|
||||
hit <- c.Command
|
||||
return nil
|
||||
})
|
||||
|
||||
@@ -82,7 +82,7 @@ func TestRouter_OnText(t *testing.T) {
|
||||
r := New(client.New("t"))
|
||||
hit := make(chan []string, 1)
|
||||
r.OnText(`^hello (\w+)$`, func(c *Context, m *api.Message) error {
|
||||
hit <- c.Values["regex_match"].([]string)
|
||||
hit <- c.RegexMatch
|
||||
return nil
|
||||
})
|
||||
|
||||
@@ -164,10 +164,7 @@ func TestRouter_NonASCIICommand(t *testing.T) {
|
||||
r := New(client.New("t"))
|
||||
hit := make(chan [2]string, 1)
|
||||
r.OnCommand("/старт", func(c *Context, m *api.Message) error {
|
||||
hit <- [2]string{
|
||||
c.Values["command"].(string),
|
||||
c.Values["command_args"].(string),
|
||||
}
|
||||
hit <- [2]string{c.Command, c.CommandArgs}
|
||||
return nil
|
||||
})
|
||||
|
||||
@@ -180,16 +177,15 @@ func TestRouter_NonASCIICommand(t *testing.T) {
|
||||
require.Equal(t, "аргумент", got[1])
|
||||
}
|
||||
|
||||
// TestRouter_CommandValuesNotLeakedOnNoMatch verifies that c.Values["command"]
|
||||
// is not set when a command entity is present but no route matches, so a
|
||||
// TestRouter_CommandValuesNotLeakedOnNoMatch verifies that c.Command is
|
||||
// empty when a command entity is present but no route matches, so a
|
||||
// subsequent text handler doesn't see stale values.
|
||||
func TestRouter_CommandValuesNotLeakedOnNoMatch(t *testing.T) {
|
||||
r := New(client.New("t"))
|
||||
// Register a text handler that should fire as fallback.
|
||||
leaked := make(chan bool, 1)
|
||||
r.OnText(`.*`, func(c *Context, m *api.Message) error {
|
||||
_, hasCmd := c.Values["command"]
|
||||
leaked <- hasCmd
|
||||
leaked <- c.Command != ""
|
||||
return nil
|
||||
})
|
||||
// No OnCommand registered, so the command entity won't match any route.
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
# Benchmarks vs top 5 Go Telegram libraries
|
||||
|
||||
**Date:** 2026-05-10
|
||||
**Environment:** Apple M4 Max · darwin/arm64 · `go1.26.2`
|
||||
**Methodology:** `go test -count=10 -bench=. -benchmem`, summarised with `benchstat` (golang.org/x/perf)
|
||||
**Source:** [`test/benchmarks/`](../../test/benchmarks/) · raw output: [`results/raw.txt`](../../test/benchmarks/results/raw.txt) · benchstat: [`results/benchstat.txt`](../../test/benchmarks/results/benchstat.txt)
|
||||
|
||||
## Libraries
|
||||
|
||||
| Lib | Module |
|
||||
|-----|--------|
|
||||
| **ours** | `github.com/lukaszraczylo/go-telegram` (this repo) |
|
||||
| gotba | `github.com/go-telegram-bot-api/telegram-bot-api/v5` |
|
||||
| telebot | `gopkg.in/telebot.v3` (tucnak) |
|
||||
| gobot | `github.com/go-telegram/bot` |
|
||||
| telego | `github.com/mymmrac/telego` |
|
||||
| echotron | `github.com/NicoNex/echotron/v3` |
|
||||
|
||||
## TL;DR
|
||||
|
||||
- **Webhook decode** (small Update): ours is **15–19% faster** than every competitor and ties telego for the lowest alloc count (11).
|
||||
- **Large Update unmarshal** (entities + reply markup + photo array): ours is **17–35% faster** with the lowest ns/op of all six. telego edges us on alloc count (31 vs 34) at the cost of ~17% more time.
|
||||
- **API call round-trip** (mock HTTP server): telego wins (36.3 µs / 48 allocs) thanks to its custom binder; ours is second (38.95 µs / 104 allocs) and beats gotba, telebot, gobot.
|
||||
- **Dispatcher routing** (20 handlers, last matches): ours is **2.5× faster than telebot and gobot** (101 ns vs 269 / 252 ns).
|
||||
|
||||
## How to read these numbers
|
||||
|
||||
- One machine, single workload, fixtures defined in [`shared/fixtures.go`](../../test/benchmarks/shared/fixtures.go). Re-run on your hardware before drawing conclusions.
|
||||
- Codecs differ across libs (we use `goccy/go-json`; most competitors use stdlib `encoding/json`). Codec choice is part of the library's value prop, so we benchmark each library as it ships, not in some artificial common-codec mode.
|
||||
- "Equivalent code path" was chosen via each library's idiomatic public API for the same logical operation. The exact code is in the bench files alongside each `BenchmarkXxx_<lib>` function — read them.
|
||||
|
||||
---
|
||||
|
||||
## 1. Webhook decode — small Update (text message)
|
||||
|
||||
Decode `shared.SmallUpdateJSON` into the library's typed `Update` struct.
|
||||
|
||||
| Lib | sec/op | B/op | allocs/op |
|
||||
|-----|--------|------|-----------|
|
||||
| **ours** | **1.743 µs ±3%** | 2.180 KiB | **11** |
|
||||
| gotba | 2.016 µs ±3% | 1.461 KiB | 17 |
|
||||
| telebot | 2.073 µs ±3% | 1.773 KiB | 17 |
|
||||
| gobot | 1.999 µs ±1% | 1.789 KiB | 16 |
|
||||
| telego | 2.026 µs ±2% | 3.060 KiB | **11** |
|
||||
| echotron | 1.973 µs ±0% | 1.680 KiB | 16 |
|
||||
|
||||
**Notes.** We use slightly more bytes because typed unions and the typed `[]UpdateType` allocate richer Go values. We win on time and tie telego on alloc count.
|
||||
|
||||
## 2. Large Update unmarshal — entities + reply markup + photo array
|
||||
|
||||
Decode `shared.LargeUpdateJSON` (text + 3 entities + 2x3 inline keyboard + 3-size photo array). Stresses each library's union/discriminator decoding.
|
||||
|
||||
| Lib | sec/op | B/op | allocs/op |
|
||||
|-----|--------|------|-----------|
|
||||
| **ours** | **6.667 µs ±4%** | 5.881 KiB | 34 |
|
||||
| gotba | 8.321 µs ±2% | 3.438 KiB | 56 |
|
||||
| telebot | 10.240 µs ±4% | 5.594 KiB | 60 |
|
||||
| gobot | 8.150 µs ±2% | 4.703 KiB | 50 |
|
||||
| telego | 7.797 µs ±1% | 6.621 KiB | **31** |
|
||||
| echotron | 8.072 µs ±0% | 4.219 KiB | 56 |
|
||||
|
||||
**Notes.** Despite the typed-union model giving us richer Go values per decode, we still produce them faster than every competitor. telego edges us by 3 allocs but pays 17% more time.
|
||||
|
||||
## 3. API call round-trip — `sendMessage` against a mock HTTP server
|
||||
|
||||
Build params → POST to local `httptest.Server` returning `{"ok":true,"result":Message}` → decode response.
|
||||
|
||||
| Lib | sec/op | B/op | allocs/op |
|
||||
|-----|--------|------|-----------|
|
||||
| ours | 38.95 µs ±3% | 11.17 KiB | 104 |
|
||||
| gotba | 41.95 µs ±2% | 10.95 KiB | 125 |
|
||||
| telebot | 43.63 µs ±0% | 13.16 KiB | 139 |
|
||||
| gobot | 61.11 µs ±1% | 13.51 KiB | 176 |
|
||||
| **telego** | **36.31 µs ±1%** | **6.556 KiB** | **48** |
|
||||
| echotron | *skipped — see below* | — | — |
|
||||
|
||||
**Notes.**
|
||||
- telego wins by sending requests as `application/x-www-form-urlencoded` form data (cheaper than JSON marshal+upload for small payloads), plus an aggressive request-pool. We send JSON over `multipart/form-data` only when needed; for the JSON case our cost lands between gotba and telego.
|
||||
- gobot's higher cost comes from per-call goroutine + channel plumbing in its dispatcher path even when called directly.
|
||||
- **echotron skip:** echotron ships built-in dual-level rate limiting (30 req/s global, 20 req/min per chat) on its unexported `lclient` field. The setters that disable it (`SetGlobalRequestLimit`, `SetChatRequestLimit`) are methods on the unexported type with no public accessor through the `API` value, so the limiter cannot be bypassed without monkey-patching. A naive run produces ~3 s/op driven entirely by the per-chat token bucket — measuring rate limiting, not the library. We skip rather than publish a misleading number. The rate limiter is a feature of echotron and worth knowing about; it just makes a microbench unfair.
|
||||
|
||||
## 4. Dispatcher routing — 20 handlers, last one matches
|
||||
|
||||
Register 20 command handlers (`/cmd0` … `/cmd19`); feed an update matching `/cmd19` so the bench measures worst-case filter chain traversal.
|
||||
|
||||
| Lib | sec/op | B/op | allocs/op |
|
||||
|-----|--------|------|-----------|
|
||||
| **ours** | **100.7 ns ±3%** | 128 B | 3 |
|
||||
| telebot | 269.2 ns ±5% | 678 B | 5 |
|
||||
| gobot | 251.5 ns ±4% | **48 B** | **1** |
|
||||
|
||||
**Notes.** We dispatch ~2.5× faster than telebot and gobot. gobot's single allocation is impressive but its routing decision is slower. telebot's higher cost reflects its richer per-update `Context` construction.
|
||||
|
||||
**Coverage caveats.**
|
||||
- **gotba** ships no built-in dispatcher; users route via a manual `switch` on `Update` fields. Benchmarking that against framework-based dispatchers would be apples-to-oranges, so it's omitted.
|
||||
- **telego** routes via a buffered channel + goroutine pool inside `telegohandler.BotHandler`. There is no public sync entry point, so the bench would conflate channel + goroutine overhead with routing cost.
|
||||
- **echotron** uses a chat-ID-keyed `Dispatcher` that fans out to per-chat `Bot` instances — a different paradigm (stateful per-chat bot loop), not directly comparable to "match this update against N handlers".
|
||||
|
||||
---
|
||||
|
||||
## How to reproduce
|
||||
|
||||
```bash
|
||||
cd test/benchmarks
|
||||
go test -count=10 -bench=. -benchmem | tee results/raw.txt
|
||||
benchstat results/raw.txt > results/benchstat.txt
|
||||
```
|
||||
|
||||
Install `benchstat` if missing: `go install golang.org/x/perf/cmd/benchstat@latest`.
|
||||
|
||||
## Bench code
|
||||
|
||||
All bench source lives under [`test/benchmarks/`](../../test/benchmarks/) as a separate Go module so competitor dependencies stay out of the root `go.mod`. The fixtures (the JSON each library decodes, the mock HTTP server) are in [`shared/fixtures.go`](../../test/benchmarks/shared/fixtures.go) — every library decodes the same bytes.
|
||||
@@ -80,7 +80,7 @@ var (
|
||||
```
|
||||
|
||||
<a name="Call"></a>
|
||||
## func [Call](<https://github.com/lukaszraczylo/go-telegram/blob/main/client/call.go#L25>)
|
||||
## func [Call](<https://github.com/lukaszraczylo/go-telegram/blob/main/client/call.go#L53>)
|
||||
|
||||
```go
|
||||
func Call[Req any, Resp any](ctx context.Context, b *Bot, method string, req Req) (Resp, error)
|
||||
@@ -93,7 +93,7 @@ It is generic over both request and response types. Methods with no parameters m
|
||||
Call is exported because the api package \(which lives outside this one\) invokes it from generated method wrappers. User code should not normally call it directly — use the typed wrappers in package api instead.
|
||||
|
||||
<a name="CallRaw"></a>
|
||||
## func [CallRaw](<https://github.com/lukaszraczylo/go-telegram/blob/main/client/call.go#L74>)
|
||||
## func [CallRaw](<https://github.com/lukaszraczylo/go-telegram/blob/main/client/call.go#L104>)
|
||||
|
||||
```go
|
||||
func CallRaw[Req any](ctx context.Context, b *Bot, method string, req Req) (json.RawMessage, error)
|
||||
@@ -296,7 +296,7 @@ type Logger interface {
|
||||
```
|
||||
|
||||
<a name="MultipartFile"></a>
|
||||
## type [MultipartFile](<https://github.com/lukaszraczylo/go-telegram/blob/main/client/multipart.go#L27-L31>)
|
||||
## type [MultipartFile](<https://github.com/lukaszraczylo/go-telegram/blob/main/client/multipart.go#L28-L32>)
|
||||
|
||||
MultipartFile describes a single file part in a multipart upload.
|
||||
|
||||
|
||||
+43
-16
@@ -13,6 +13,7 @@ Package dispatch provides a typed router for Telegram updates. It consumes any t
|
||||
- [Variables](<#variables>)
|
||||
- [type Context](<#Context>)
|
||||
- [func NewContext\(ctx context.Context, b \*client.Bot, u \*api.Update\) \*Context](<#NewContext>)
|
||||
- [func \(c \*Context\) Set\(key string, val any\)](<#Context.Set>)
|
||||
- [type Filter](<#Filter>)
|
||||
- [func All\[T any\]\(filters ...Filter\[T\]\) Filter\[T\]](<#All>)
|
||||
- [func Any\[T any\]\(filters ...Filter\[T\]\) Filter\[T\]](<#Any>)
|
||||
@@ -61,6 +62,7 @@ Package dispatch provides a typed router for Telegram updates. It consumes any t
|
||||
- [func \(r \*Router\) OnRemovedChatBoost\(h Handler\[\*api.ChatBoostRemoved\]\)](<#Router.OnRemovedChatBoost>)
|
||||
- [func \(r \*Router\) OnShippingQuery\(h Handler\[\*api.ShippingQuery\]\)](<#Router.OnShippingQuery>)
|
||||
- [func \(r \*Router\) OnText\(pattern string, h Handler\[\*api.Message\]\)](<#Router.OnText>)
|
||||
- [func \(r \*Router\) Process\(ctx context.Context, u \*api.Update\) error](<#Router.Process>)
|
||||
- [func \(r \*Router\) Run\(ctx context.Context, u transport.Updater\) error](<#Router.Run>)
|
||||
- [func \(r \*Router\) Use\(mw Middleware\[\*api.Update\]\)](<#Router.Use>)
|
||||
- [type RouterOption](<#RouterOption>)
|
||||
@@ -90,7 +92,7 @@ var ErrEndGroups = errors.New("dispatch: end groups")
|
||||
```
|
||||
|
||||
<a name="Context"></a>
|
||||
## type [Context](<https://github.com/lukaszraczylo/go-telegram/blob/main/dispatch/context.go#L29-L34>)
|
||||
## type [Context](<https://github.com/lukaszraczylo/go-telegram/blob/main/dispatch/context.go#L41-L49>)
|
||||
|
||||
Context bundles the per\-update state every handler receives.
|
||||
|
||||
@@ -100,25 +102,30 @@ Bot is the API client. Handlers reply by calling api.SendMessage\(c.Ctx, c.Bot,
|
||||
|
||||
Update is the raw update; payload\-typed handlers also receive a narrowed pointer to one of its sub\-fields.
|
||||
|
||||
Values is a per\-update bag matchers populate. Conventional keys:
|
||||
Command, CommandArgs and RegexMatch are populated by the router for the matching route kind; they replace the previous "command", "command\_args" and "regex\_match" entries in Values, which were the only conventional keys. Values remains for user\-defined custom keys.
|
||||
|
||||
```
|
||||
"command": string, the matched bot command (e.g. "/start")
|
||||
"command_args": string, everything after the command
|
||||
"regex_match": []string, regex sub-matches when OnText matches
|
||||
```
|
||||
Command is the matched bot command \(e.g. "/start"\); empty when the route is not a command match.
|
||||
|
||||
CommandArgs is everything after the command; empty when no command matched or the command had no trailing text.
|
||||
|
||||
RegexMatch is the regex sub\-matches when an OnText/OnCallback regex route matched; nil otherwise.
|
||||
|
||||
Values is lazily allocated for user\-defined keys. Handlers that don't write pay no allocation. Reads against a nil map return the zero value. Writers must use Set instead of indexing the map directly.
|
||||
|
||||
```go
|
||||
type Context struct {
|
||||
Ctx context.Context
|
||||
Bot *client.Bot
|
||||
Update *api.Update
|
||||
Values map[string]any
|
||||
Ctx context.Context
|
||||
Bot *client.Bot
|
||||
Update *api.Update
|
||||
Command string
|
||||
CommandArgs string
|
||||
RegexMatch []string
|
||||
Values map[string]any
|
||||
}
|
||||
```
|
||||
|
||||
<a name="NewContext"></a>
|
||||
### func [NewContext](<https://github.com/lukaszraczylo/go-telegram/blob/main/dispatch/context.go#L38>)
|
||||
### func [NewContext](<https://github.com/lukaszraczylo/go-telegram/blob/main/dispatch/context.go#L53>)
|
||||
|
||||
```go
|
||||
func NewContext(ctx context.Context, b *client.Bot, u *api.Update) *Context
|
||||
@@ -126,6 +133,15 @@ func NewContext(ctx context.Context, b *client.Bot, u *api.Update) *Context
|
||||
|
||||
NewContext constructs a Context. Used by Router internally; exposed for custom test harnesses.
|
||||
|
||||
<a name="Context.Set"></a>
|
||||
### func \(\*Context\) [Set](<https://github.com/lukaszraczylo/go-telegram/blob/main/dispatch/context.go#L60>)
|
||||
|
||||
```go
|
||||
func (c *Context) Set(key string, val any)
|
||||
```
|
||||
|
||||
Set writes key/val into Values, allocating the map on first use. Use this instead of \`c.Values\[k\] = v\` so the no\-write path stays allocation\-free.
|
||||
|
||||
<a name="Filter"></a>
|
||||
## type [Filter](<https://github.com/lukaszraczylo/go-telegram/blob/main/dispatch/filter.go#L9>)
|
||||
|
||||
@@ -585,18 +601,29 @@ OnText registers a handler for messages whose Text matches the regex.
|
||||
|
||||
Panics at registration time if pattern is not a valid regular expression.
|
||||
|
||||
<a name="Router.Run"></a>
|
||||
### func \(\*Router\) [Run](<https://github.com/lukaszraczylo/go-telegram/blob/main/dispatch/router.go#L303>)
|
||||
<a name="Router.Process"></a>
|
||||
### func \(\*Router\) [Process](<https://github.com/lukaszraczylo/go-telegram/blob/main/dispatch/router.go#L310>)
|
||||
|
||||
```go
|
||||
func (r *Router) Run(ctx context.Context, u transport.Updater) error
|
||||
func (r *Router) Process(ctx context.Context, u *api.Update) error
|
||||
```
|
||||
|
||||
Run consumes the Updater and dispatches each update. It blocks until the Updater's channel is closed or ctx is cancelled.
|
||||
|
||||
By default updates are processed concurrently \(up to WithMaxConcurrency\(50\) goroutines\). Handlers for different updates may therefore run simultaneously; shared state must be protected. Pass WithMaxConcurrency\(0\) to New to restore serial \(legacy\) behaviour.
|
||||
|
||||
Run waits for all in\-flight handlers to finish before returning.
|
||||
Run waits for all in\-flight handlers to finish before returning. Process runs a single update through the router's middleware and handler chain synchronously. Entry point for callers sourcing updates outside the standard transport.Updater flow — custom webhook frameworks, message\-bus consumers, or tests driving the router without spinning up Run.
|
||||
|
||||
Honours the router's global middleware \(Use\) but bypasses the concurrency semaphore wired up by Run; the caller controls parallelism.
|
||||
|
||||
<a name="Router.Run"></a>
|
||||
### func \(\*Router\) [Run](<https://github.com/lukaszraczylo/go-telegram/blob/main/dispatch/router.go#L322>)
|
||||
|
||||
```go
|
||||
func (r *Router) Run(ctx context.Context, u transport.Updater) error
|
||||
```
|
||||
|
||||
|
||||
|
||||
<a name="Router.Use"></a>
|
||||
### func \(\*Router\) [Use](<https://github.com/lukaszraczylo/go-telegram/blob/main/dispatch/router.go#L141>)
|
||||
|
||||
@@ -154,7 +154,7 @@ type Updater interface {
|
||||
```
|
||||
|
||||
<a name="WebhookOption"></a>
|
||||
## type [WebhookOption](<https://github.com/lukaszraczylo/go-telegram/blob/main/transport/webhook.go#L38>)
|
||||
## type [WebhookOption](<https://github.com/lukaszraczylo/go-telegram/blob/main/transport/webhook.go#L57>)
|
||||
|
||||
WebhookOption configures a WebhookServer at construction time.
|
||||
|
||||
@@ -163,7 +163,7 @@ type WebhookOption func(*webhookOptions)
|
||||
```
|
||||
|
||||
<a name="WithBufferSize"></a>
|
||||
### func [WithBufferSize](<https://github.com/lukaszraczylo/go-telegram/blob/main/transport/webhook.go#L46>)
|
||||
### func [WithBufferSize](<https://github.com/lukaszraczylo/go-telegram/blob/main/transport/webhook.go#L65>)
|
||||
|
||||
```go
|
||||
func WithBufferSize(n int) WebhookOption
|
||||
@@ -172,7 +172,7 @@ func WithBufferSize(n int) WebhookOption
|
||||
WithBufferSize sets the size of the updates channel buffer. Default is 64.
|
||||
|
||||
<a name="WebhookServer"></a>
|
||||
## type [WebhookServer](<https://github.com/lukaszraczylo/go-telegram/blob/main/transport/webhook.go#L24-L35>)
|
||||
## type [WebhookServer](<https://github.com/lukaszraczylo/go-telegram/blob/main/transport/webhook.go#L43-L54>)
|
||||
|
||||
WebhookServer implements Updater by exposing an http.Handler that receives updates from Telegram. It can be mounted on the user's own HTTP server \(via ServeHTTP\) or run standalone \(via ListenAndServe\).
|
||||
|
||||
@@ -185,7 +185,7 @@ type WebhookServer struct {
|
||||
```
|
||||
|
||||
<a name="NewWebhookServer"></a>
|
||||
### func [NewWebhookServer](<https://github.com/lukaszraczylo/go-telegram/blob/main/transport/webhook.go#L52>)
|
||||
### func [NewWebhookServer](<https://github.com/lukaszraczylo/go-telegram/blob/main/transport/webhook.go#L71>)
|
||||
|
||||
```go
|
||||
func NewWebhookServer(b *client.Bot, opts ...WebhookOption) *WebhookServer
|
||||
@@ -194,7 +194,7 @@ func NewWebhookServer(b *client.Bot, opts ...WebhookOption) *WebhookServer
|
||||
NewWebhookServer constructs a WebhookServer with default buffer size \(64\). Use WithBufferSize to override.
|
||||
|
||||
<a name="WebhookServer.ListenAndServe"></a>
|
||||
### func \(\*WebhookServer\) [ListenAndServe](<https://github.com/lukaszraczylo/go-telegram/blob/main/transport/webhook.go#L150>)
|
||||
### func \(\*WebhookServer\) [ListenAndServe](<https://github.com/lukaszraczylo/go-telegram/blob/main/transport/webhook.go#L168>)
|
||||
|
||||
```go
|
||||
func (w *WebhookServer) ListenAndServe(ctx context.Context, addr string) error
|
||||
@@ -203,7 +203,7 @@ func (w *WebhookServer) ListenAndServe(ctx context.Context, addr string) error
|
||||
ListenAndServe starts an HTTP server on addr and blocks until Stop is called \(which triggers Shutdown with the caller's context\) or the server returns an error other than http.ErrServerClosed. Callers must invoke Stop\(ctx\) to cleanly shut down the server; the ctx passed here is only used as the server's base context for incoming requests.
|
||||
|
||||
<a name="WebhookServer.Run"></a>
|
||||
### func \(\*WebhookServer\) [Run](<https://github.com/lukaszraczylo/go-telegram/blob/main/transport/webhook.go#L71>)
|
||||
### func \(\*WebhookServer\) [Run](<https://github.com/lukaszraczylo/go-telegram/blob/main/transport/webhook.go#L90>)
|
||||
|
||||
```go
|
||||
func (w *WebhookServer) Run(ctx context.Context) error
|
||||
@@ -212,7 +212,7 @@ func (w *WebhookServer) Run(ctx context.Context) error
|
||||
Run implements Updater. It blocks until Stop is called or ctx is cancelled. If the server has not been started via ListenAndServe, Run only watches for shutdown — the user is expected to mount ServeHTTP on their own router.
|
||||
|
||||
<a name="WebhookServer.ServeHTTP"></a>
|
||||
### func \(\*WebhookServer\) [ServeHTTP](<https://github.com/lukaszraczylo/go-telegram/blob/main/transport/webhook.go#L97>)
|
||||
### func \(\*WebhookServer\) [ServeHTTP](<https://github.com/lukaszraczylo/go-telegram/blob/main/transport/webhook.go#L116>)
|
||||
|
||||
```go
|
||||
func (w *WebhookServer) ServeHTTP(rw http.ResponseWriter, r *http.Request)
|
||||
@@ -221,7 +221,7 @@ func (w *WebhookServer) ServeHTTP(rw http.ResponseWriter, r *http.Request)
|
||||
ServeHTTP implements http.Handler. Telegram POSTs each update as JSON to this endpoint. Non\-POST requests get 405; bad bodies get 400; secret token mismatches get 401.
|
||||
|
||||
<a name="WebhookServer.Stop"></a>
|
||||
### func \(\*WebhookServer\) [Stop](<https://github.com/lukaszraczylo/go-telegram/blob/main/transport/webhook.go#L83>)
|
||||
### func \(\*WebhookServer\) [Stop](<https://github.com/lukaszraczylo/go-telegram/blob/main/transport/webhook.go#L102>)
|
||||
|
||||
```go
|
||||
func (w *WebhookServer) Stop(ctx context.Context) error
|
||||
@@ -230,7 +230,7 @@ func (w *WebhookServer) Stop(ctx context.Context) error
|
||||
Stop implements Updater.
|
||||
|
||||
<a name="WebhookServer.Updates"></a>
|
||||
### func \(\*WebhookServer\) [Updates](<https://github.com/lukaszraczylo/go-telegram/blob/main/transport/webhook.go#L65>)
|
||||
### func \(\*WebhookServer\) [Updates](<https://github.com/lukaszraczylo/go-telegram/blob/main/transport/webhook.go#L84>)
|
||||
|
||||
```go
|
||||
func (w *WebhookServer) Updates() <-chan api.Update
|
||||
|
||||
@@ -21,7 +21,7 @@ func handleStart(c *dispatch.Context, m *api.Message) error {
|
||||
}
|
||||
|
||||
func handleCallback(c *dispatch.Context, q *api.CallbackQuery) error {
|
||||
groups := c.Values["regex_match"].([]string)
|
||||
groups := c.RegexMatch
|
||||
current, _ := strconv.Atoi(groups[1])
|
||||
if groups[2] == "inc" {
|
||||
current++
|
||||
|
||||
@@ -42,7 +42,7 @@ const (
|
||||
func makeCtx(bot *client.Bot, upd *api.Update, extra map[string]any) *dispatch.Context {
|
||||
c := dispatch.NewContext(context.Background(), bot, upd)
|
||||
for k, v := range extra {
|
||||
c.Values[k] = v
|
||||
c.Set(k, v)
|
||||
}
|
||||
return c
|
||||
}
|
||||
@@ -82,7 +82,9 @@ func TestHandleStart_SendsInitialKeyboard(t *testing.T) {
|
||||
|
||||
func callbackCtx(bot *client.Bot, q *api.CallbackQuery, groups []string) *dispatch.Context {
|
||||
upd := &api.Update{UpdateID: 1, CallbackQuery: q}
|
||||
return makeCtx(bot, upd, map[string]any{"regex_match": groups})
|
||||
c := makeCtx(bot, upd, nil)
|
||||
c.RegexMatch = groups
|
||||
return c
|
||||
}
|
||||
|
||||
func callbackQuery(data string, msgID int64, chatID int64) *api.CallbackQuery {
|
||||
|
||||
@@ -111,8 +111,7 @@ func main() {
|
||||
|
||||
// page:<n> callbacks — edit message in-place.
|
||||
router.OnCallback(`^page:(\d+)$`, func(c *dispatch.Context, q *api.CallbackQuery) error {
|
||||
groups := c.Values["regex_match"].([]string)
|
||||
page, _ := strconv.Atoi(groups[1])
|
||||
page, _ := strconv.Atoi(c.RegexMatch[1])
|
||||
|
||||
// Acknowledge the tap first.
|
||||
_, _ = api.AnswerCallbackQuery(c.Ctx, c.Bot, &api.AnswerCallbackQueryParams{
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
# Cross-library benchmarks
|
||||
|
||||
Apples-to-apples micro-benchmarks comparing `lukaszraczylo/go-telegram` against the five most-starred Go Telegram libraries:
|
||||
|
||||
- `github.com/go-telegram-bot-api/telegram-bot-api/v5`
|
||||
- `gopkg.in/telebot.v3` (tucnak)
|
||||
- `github.com/go-telegram/bot`
|
||||
- `github.com/mymmrac/telego`
|
||||
- `github.com/NicoNex/echotron/v3`
|
||||
|
||||
Lives in its own Go module so competitor dependencies don't leak into the main repo's `go.mod`.
|
||||
|
||||
## Run
|
||||
|
||||
```bash
|
||||
go test -count=10 -bench=. -benchmem | tee results/raw.txt
|
||||
go install golang.org/x/perf/cmd/benchstat@latest # one-time
|
||||
benchstat results/raw.txt > results/benchstat.txt
|
||||
```
|
||||
|
||||
## Hot paths covered
|
||||
|
||||
| File | Path |
|
||||
|------|------|
|
||||
| `webhook_bench_test.go` | Decode small text-message Update from JSON |
|
||||
| `unmarshal_bench_test.go` | Decode large Update (entities + reply markup + photo array) |
|
||||
| `call_bench_test.go` | `sendMessage` round-trip against `httptest.Server` |
|
||||
| `dispatch_bench_test.go` | Route an Update through 20 registered handlers (worst-case match) |
|
||||
|
||||
## Fixtures
|
||||
|
||||
`shared/fixtures.go` defines the JSON payloads and the mock HTTP server. Every library decodes the same bytes; every round-trip hits the same canned response.
|
||||
|
||||
## Latest results
|
||||
|
||||
See [`../../docs/benchmarks/2026-05-10-comparison.md`](../../docs/benchmarks/2026-05-10-comparison.md) for the rendered comparison.
|
||||
@@ -0,0 +1,166 @@
|
||||
// Round-trip benchmarks: build a SendMessage request, POST it to a local
|
||||
// httptest.Server returning a canned `{"ok":true,"result":Message}` body,
|
||||
// decode the response. Measures marshal + transport + unmarshal end-to-end.
|
||||
//
|
||||
// Each library's idiomatic "send a text message" call path is exercised
|
||||
// through its public API. The mock server replies identically for every path,
|
||||
// so any difference comes from serialization, HTTP plumbing, or response
|
||||
// decoding inside each library.
|
||||
package benchmarks
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/lukaszraczylo/go-telegram/api"
|
||||
"github.com/lukaszraczylo/go-telegram/client"
|
||||
"github.com/lukaszraczylo/go-telegram/test/benchmarks/shared"
|
||||
|
||||
echotron "github.com/NicoNex/echotron/v3"
|
||||
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
|
||||
gobot "github.com/go-telegram/bot"
|
||||
telego "github.com/mymmrac/telego"
|
||||
tele "gopkg.in/telebot.v3"
|
||||
)
|
||||
|
||||
// Telegram-format token (digits:[\w-]{35}). telego enforces this format on construction.
|
||||
const benchToken = "1234567890:ABCDEFGHIJKLMNOPQRSTUVWXYZ_ab123456"
|
||||
|
||||
// BenchmarkCall_ours — lukaszraczylo/go-telegram.
|
||||
func BenchmarkCall_ours(b *testing.B) {
|
||||
srv := shared.NewMockServer()
|
||||
defer srv.Close()
|
||||
bot := client.New(benchToken, client.WithBaseURL(srv.URL))
|
||||
ctx := context.Background()
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for b.Loop() {
|
||||
_, err := api.SendMessage(ctx, bot, &api.SendMessageParams{
|
||||
ChatID: api.ChatIDFromInt(42),
|
||||
Text: "hello",
|
||||
})
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// BenchmarkCall_gotba — go-telegram-bot-api/telegram-bot-api/v5.
|
||||
func BenchmarkCall_gotba(b *testing.B) {
|
||||
srv := shared.NewMockServer()
|
||||
defer srv.Close()
|
||||
// Endpoint is sprintf'd with token + method.
|
||||
endpoint := srv.URL + "/bot%s/%s"
|
||||
bot, err := tgbotapi.NewBotAPIWithClient(benchToken, endpoint, &http.Client{})
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
msg := tgbotapi.NewMessage(42, "hello")
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for b.Loop() {
|
||||
if _, err := bot.Send(msg); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// BenchmarkCall_telebot — gopkg.in/telebot.v3 (tucnak).
|
||||
func BenchmarkCall_telebot(b *testing.B) {
|
||||
srv := shared.NewMockServer()
|
||||
defer srv.Close()
|
||||
bot, err := tele.NewBot(tele.Settings{
|
||||
Token: benchToken,
|
||||
URL: srv.URL,
|
||||
Synchronous: true,
|
||||
Offline: true, // skip eager getMe call; we test sending
|
||||
})
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
chat := &tele.Chat{ID: 42}
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for b.Loop() {
|
||||
if _, err := bot.Send(chat, "hello"); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// BenchmarkCall_gobot — go-telegram/bot.
|
||||
func BenchmarkCall_gobot(b *testing.B) {
|
||||
srv := shared.NewMockServer()
|
||||
defer srv.Close()
|
||||
bot, err := gobot.New(benchToken,
|
||||
gobot.WithServerURL(srv.URL),
|
||||
gobot.WithSkipGetMe(),
|
||||
)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
ctx := context.Background()
|
||||
params := &gobot.SendMessageParams{ChatID: int64(42), Text: "hello"}
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for b.Loop() {
|
||||
if _, err := bot.SendMessage(ctx, params); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// BenchmarkCall_telego — mymmrac/telego.
|
||||
func BenchmarkCall_telego(b *testing.B) {
|
||||
srv := shared.NewMockServer()
|
||||
defer srv.Close()
|
||||
bot, err := telego.NewBot(benchToken, telego.WithAPIServer(srv.URL))
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
ctx := context.Background()
|
||||
params := &telego.SendMessageParams{
|
||||
ChatID: telego.ChatID{ID: 42},
|
||||
Text: "hello",
|
||||
}
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for b.Loop() {
|
||||
if _, err := bot.SendMessage(ctx, params); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// BenchmarkCall_echotron — NicoNex/echotron/v3.
|
||||
//
|
||||
// echotron expects a base URL ending in /bot<token>/ and ships built-in
|
||||
// dual-level rate limiting (global 30/s, per-chat 20/min) on its unexported
|
||||
// lclient field. The setters (SetGlobalRequestLimit / SetChatRequestLimit)
|
||||
// are methods on the unexported type and have no public accessor through
|
||||
// the API value, so the rate limiter cannot be disabled from outside the
|
||||
// package without monkey-patching.
|
||||
//
|
||||
// Running this bench against the real path produces ~3s/op driven entirely
|
||||
// by the per-chat token bucket — measuring rate limiting, not the library.
|
||||
// We skip rather than publish a misleading number; the rate limiter is a
|
||||
// feature of echotron and is documented as a caveat in the report.
|
||||
func BenchmarkCall_echotron(b *testing.B) {
|
||||
b.Skip("echotron has built-in rate limiting that cannot be disabled via the public API; see comment")
|
||||
srv := shared.NewMockServer()
|
||||
defer srv.Close()
|
||||
base := srv.URL + "/bot" + benchToken + "/"
|
||||
api := echotron.CustomAPI(base, benchToken)
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for b.Loop() {
|
||||
if _, err := api.SendMessage("hello", 42, nil); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// silence unused-import if a build tag strips a lib.
|
||||
var _ = strings.NewReader
|
||||
@@ -0,0 +1,118 @@
|
||||
// Dispatcher routing benchmarks: register 20 handlers across each library's
|
||||
// dispatcher, feed an update that matches the LAST-registered handler, and
|
||||
// measure cost per dispatch. Worst-case filter chain traversal.
|
||||
//
|
||||
// Coverage notes (see results/raw.txt and report for the full caveats):
|
||||
//
|
||||
// - ours, telebot, gobot expose a synchronous single-update entry point
|
||||
// (Process / ProcessUpdate). Bench measures that path directly.
|
||||
// - gotba (go-telegram-bot-api/v5) ships no built-in dispatcher; users
|
||||
// route via a manual switch on Update fields. Skipped here — would be
|
||||
// comparing our framework against a hand-written switch.
|
||||
// - telego routes via a buffered channel + goroutine pool inside
|
||||
// telegohandler.BotHandler. There is no public sync entry, so the bench
|
||||
// would conflate channel + goroutine overhead with routing cost. Skipped.
|
||||
// - echotron uses a chat-ID-keyed Dispatcher that fans out to per-chat Bot
|
||||
// instances; it's a different paradigm (stateful per-chat bot loop), so
|
||||
// not directly comparable to "match this update against N handlers".
|
||||
package benchmarks
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/lukaszraczylo/go-telegram/api"
|
||||
"github.com/lukaszraczylo/go-telegram/client"
|
||||
"github.com/lukaszraczylo/go-telegram/dispatch"
|
||||
|
||||
gobot "github.com/go-telegram/bot"
|
||||
gobotmodels "github.com/go-telegram/bot/models"
|
||||
tele "gopkg.in/telebot.v3"
|
||||
)
|
||||
|
||||
const dispatchN = 20
|
||||
|
||||
// matchCmd is the command the LAST-registered handler matches.
|
||||
const matchCmd = "/cmd19"
|
||||
|
||||
func BenchmarkDispatch_ours(b *testing.B) {
|
||||
r := dispatch.New(client.New(benchToken))
|
||||
noop := func(c *dispatch.Context, m *api.Message) error { return nil }
|
||||
for i := 0; i < dispatchN; i++ {
|
||||
r.OnCommand(fmt.Sprintf("/cmd%d", i), noop)
|
||||
}
|
||||
u := &api.Update{
|
||||
UpdateID: 1,
|
||||
Message: &api.Message{
|
||||
MessageID: 1,
|
||||
Date: 0,
|
||||
Chat: api.Chat{ID: 42, Type: api.ChatTypePrivate},
|
||||
Text: matchCmd,
|
||||
Entities: []api.MessageEntity{
|
||||
{Type: api.MessageEntityTypeBotCommand, Offset: 0, Length: int64(len(matchCmd))},
|
||||
},
|
||||
},
|
||||
}
|
||||
ctx := context.Background()
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for b.Loop() {
|
||||
if err := r.Process(ctx, u); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkDispatch_telebot(b *testing.B) {
|
||||
bot, err := tele.NewBot(tele.Settings{Token: benchToken, Synchronous: true, Offline: true})
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
noop := func(c tele.Context) error { return nil }
|
||||
for i := 0; i < dispatchN; i++ {
|
||||
bot.Handle(fmt.Sprintf("/cmd%d", i), noop)
|
||||
}
|
||||
u := tele.Update{
|
||||
ID: 1,
|
||||
Message: &tele.Message{
|
||||
ID: 1,
|
||||
Chat: &tele.Chat{ID: 42, Type: tele.ChatPrivate},
|
||||
Sender: &tele.User{ID: 42},
|
||||
Text: matchCmd,
|
||||
Entities: []tele.MessageEntity{
|
||||
{Type: tele.EntityCommand, Offset: 0, Length: len(matchCmd)},
|
||||
},
|
||||
},
|
||||
}
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for b.Loop() {
|
||||
bot.ProcessUpdate(u)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkDispatch_gobot(b *testing.B) {
|
||||
srvless := func(ctx context.Context, b *gobot.Bot, update *gobotmodels.Update) {}
|
||||
bot, err := gobot.New(benchToken, gobot.WithSkipGetMe(), gobot.WithDefaultHandler(srvless))
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
for i := 0; i < dispatchN; i++ {
|
||||
bot.RegisterHandler(gobot.HandlerTypeMessageText, fmt.Sprintf("/cmd%d", i), gobot.MatchTypeExact, srvless)
|
||||
}
|
||||
u := &gobotmodels.Update{
|
||||
ID: 1,
|
||||
Message: &gobotmodels.Message{
|
||||
ID: 1,
|
||||
Chat: gobotmodels.Chat{ID: 42, Type: gobotmodels.ChatTypePrivate},
|
||||
Text: matchCmd,
|
||||
},
|
||||
}
|
||||
ctx := context.Background()
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for b.Loop() {
|
||||
bot.ProcessUpdate(ctx, u)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
module github.com/lukaszraczylo/go-telegram/test/benchmarks
|
||||
|
||||
go 1.25.7
|
||||
|
||||
replace github.com/lukaszraczylo/go-telegram => ../../
|
||||
|
||||
require (
|
||||
github.com/NicoNex/echotron/v3 v3.45.0
|
||||
github.com/go-telegram-bot-api/telegram-bot-api/v5 v5.5.1
|
||||
github.com/go-telegram/bot v1.20.0
|
||||
github.com/lukaszraczylo/go-telegram v0.0.0-00010101000000-000000000000
|
||||
github.com/mymmrac/telego v1.8.0
|
||||
gopkg.in/telebot.v3 v3.3.8
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/andybalholm/brotli v1.2.0 // indirect
|
||||
github.com/bytedance/gopkg v0.1.3 // indirect
|
||||
github.com/bytedance/sonic v1.15.0 // indirect
|
||||
github.com/bytedance/sonic/loader v0.5.0 // indirect
|
||||
github.com/cloudwego/base64x v0.1.6 // indirect
|
||||
github.com/goccy/go-json v0.10.6 // indirect
|
||||
github.com/grbit/go-json v0.11.0 // indirect
|
||||
github.com/klauspost/compress v1.18.2 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.9 // indirect
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||
github.com/valyala/fasthttp v1.69.0 // indirect
|
||||
github.com/valyala/fastjson v1.6.10 // indirect
|
||||
golang.org/x/arch v0.0.0-20210923205945-b76863e36670 // indirect
|
||||
golang.org/x/sys v0.39.0 // indirect
|
||||
golang.org/x/time v0.5.0 // indirect
|
||||
)
|
||||
@@ -0,0 +1,905 @@
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
|
||||
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
|
||||
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
|
||||
cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
|
||||
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
|
||||
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
|
||||
cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
|
||||
cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
|
||||
cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
|
||||
cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
|
||||
cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
|
||||
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
|
||||
cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
|
||||
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
|
||||
cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI=
|
||||
cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk=
|
||||
cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY=
|
||||
cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg=
|
||||
cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8=
|
||||
cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0=
|
||||
cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY=
|
||||
cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM=
|
||||
cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY=
|
||||
cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ=
|
||||
cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI=
|
||||
cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4=
|
||||
cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc=
|
||||
cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA=
|
||||
cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w99A=
|
||||
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
|
||||
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
|
||||
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
|
||||
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
|
||||
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
|
||||
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
|
||||
cloud.google.com/go/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow=
|
||||
cloud.google.com/go/compute v1.3.0/go.mod h1:cCZiE1NHEtai4wiufUhW8I8S1JKkAnhnQJWM7YD99wM=
|
||||
cloud.google.com/go/compute v1.5.0/go.mod h1:9SMHyhJlzhlkJqrPAc839t2BZFTSk6Jdj6mkzQJeu0M=
|
||||
cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz/FMzPu0s=
|
||||
cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU=
|
||||
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
|
||||
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
|
||||
cloud.google.com/go/firestore v1.6.1/go.mod h1:asNXNOzBdyVQmEU+ggO8UPodTkEVFW5Qx+rwHnAz+EY=
|
||||
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
|
||||
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
|
||||
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
|
||||
cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
|
||||
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
|
||||
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
|
||||
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
|
||||
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
|
||||
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
|
||||
cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo=
|
||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
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/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
|
||||
github.com/NicoNex/echotron/v3 v3.45.0 h1:hORujGwc6X2yaiHZIt8/rYZR48L524YtdiHxpqBwlko=
|
||||
github.com/NicoNex/echotron/v3 v3.45.0/go.mod h1:7LvjveJmezuUOeaoA3nzQduNlSPQYfq219Z+baKY04Q=
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
|
||||
github.com/andybalholm/brotli v1.2.0 h1:ukwgCxwYrmACq68yiUqwIWnGY0cTPox/M94sVwToPjQ=
|
||||
github.com/andybalholm/brotli v1.2.0/go.mod h1:rzTDkvFWvIrjDXZHkuS16NPggd91W3kUSvPlQ1pLaKY=
|
||||
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
||||
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
|
||||
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
|
||||
github.com/armon/go-metrics v0.3.10/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc=
|
||||
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||
github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||
github.com/bytedance/gopkg v0.1.3 h1:TPBSwH8RsouGCBcMBktLt1AymVo2TVsBVCY4b6TnZ/M=
|
||||
github.com/bytedance/gopkg v0.1.3/go.mod h1:576VvJ+eJgyCzdjS+c4+77QF3p7ubbtiKARP3TxducM=
|
||||
github.com/bytedance/sonic v1.15.0 h1:/PXeWFaR5ElNcVE84U0dOHjiMHQOwNIx3K4ymzh/uSE=
|
||||
github.com/bytedance/sonic v1.15.0/go.mod h1:tFkWrPz0/CUCLEF4ri4UkHekCIcdnkqXw9VduqpJh0k=
|
||||
github.com/bytedance/sonic/loader v0.5.0 h1:gXH3KVnatgY7loH5/TkeVyXPfESoqSBSBEiDd5VjlgE=
|
||||
github.com/bytedance/sonic/loader v0.5.0/go.mod h1:AR4NYCk5DdzZizZ5djGqQ92eEhCCcdf5x77udYiSJRo=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||
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/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag=
|
||||
github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cloudwego/base64x v0.1.6 h1:t11wG9AECkCDk5fMSoxmufanudBtJ+/HemLstXDLI2M=
|
||||
github.com/cloudwego/base64x v0.1.6/go.mod h1:OFcloc187FXDaYHvrNIjxSe8ncn0OOM8gEHfghB2IPU=
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||
github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
|
||||
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
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/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||
github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po=
|
||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
|
||||
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
|
||||
github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
|
||||
github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
|
||||
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
|
||||
github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps=
|
||||
github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
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=
|
||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
|
||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
|
||||
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.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/go-telegram-bot-api/telegram-bot-api/v5 v5.5.1 h1:wG8n/XJQ07TmjbITcGiUaOtXxdrINDz1b0J1w0SzqDc=
|
||||
github.com/go-telegram-bot-api/telegram-bot-api/v5 v5.5.1/go.mod h1:A2S0CWkNylc2phvKXWBBdD3K0iGnDBGbzRpISP2zBl8=
|
||||
github.com/go-telegram/bot v1.20.0 h1:4Pea/qTidSspr4WBJw9FbHUMNhYeqszBqQUfsQEyFbc=
|
||||
github.com/go-telegram/bot v1.20.0/go.mod h1:i2TRs7fXWIeaceF3z7KzsMt/he0TwkVC680mvdTFYeM=
|
||||
github.com/goccy/go-json v0.10.6 h1:p8HrPJzOakx/mn/bQtjgNjdTcN+/S6FcG2CTtQOrHVU=
|
||||
github.com/goccy/go-json v0.10.6/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
|
||||
github.com/goccy/go-yaml v1.9.5/go.mod h1:U/jl18uSupI5rdI2jmuCswEA2htH9eXfferR3KfscvA=
|
||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
|
||||
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
|
||||
github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8=
|
||||
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
|
||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
|
||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM=
|
||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
|
||||
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||
github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||
github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk=
|
||||
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
||||
github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0=
|
||||
github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM=
|
||||
github.com/googleapis/gax-go/v2 v2.2.0/go.mod h1:as02EH8zWkzwUoLbBaFeQ+arQaj/OthfcblKl4IGNaM=
|
||||
github.com/googleapis/gax-go/v2 v2.3.0/go.mod h1:b8LNqSzNabLiUpXKkY7HAR5jr6bIT99EXz9pXxye9YM=
|
||||
github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK9wbMD5+iXC6c=
|
||||
github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
|
||||
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/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
|
||||
github.com/hashicorp/consul/api v1.12.0/go.mod h1:6pVBMo0ebnYdt2S3H87XhekM/HHrUoTD2XXb/VrZVy0=
|
||||
github.com/hashicorp/consul/sdk v0.8.0/go.mod h1:GBvyrGALthsZObzUGsfgHZQDXjg4lOjagTIwIR1vPms=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
|
||||
github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
|
||||
github.com/hashicorp/go-hclog v1.2.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
|
||||
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
|
||||
github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
|
||||
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
|
||||
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
|
||||
github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA=
|
||||
github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs=
|
||||
github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8=
|
||||
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
|
||||
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
|
||||
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
|
||||
github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc=
|
||||
github.com/hashicorp/memberlist v0.3.0/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE=
|
||||
github.com/hashicorp/serf v0.9.6/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4=
|
||||
github.com/hashicorp/serf v0.9.7/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4=
|
||||
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/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
|
||||
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/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
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=
|
||||
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
|
||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
|
||||
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/klauspost/compress v1.18.2 h1:iiPHWW0YrcFgpBYhsA6D1+fqHssJscY/Tm/y2Uqnapk=
|
||||
github.com/klauspost/compress v1.18.2/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4=
|
||||
github.com/klauspost/cpuid/v2 v2.2.9 h1:66ze0taIn2H33fBvCkXuv9BmCwDfafmiIVpKV9kKGuY=
|
||||
github.com/klauspost/cpuid/v2 v2.2.9/go.mod h1:rqkxqrZ1EhYM9G+hXH7YdowN5R5RGN6NK4QwQ3WMXF8=
|
||||
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/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
||||
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=
|
||||
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
|
||||
github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
|
||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
|
||||
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
|
||||
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso=
|
||||
github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI=
|
||||
github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
|
||||
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
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.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/mymmrac/telego v1.8.0 h1:EvIprWo9Cn0MHgumvvqNXPAXO1yJj3pu2cdCCeDxbow=
|
||||
github.com/mymmrac/telego v1.8.0/go.mod h1:pdLV346EgVuq7Xrh3kMggeBiazeHhsdEoK0RTEOPXRM=
|
||||
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||
github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
|
||||
github.com/pelletier/go-toml/v2 v2.0.5/go.mod h1:OMHamSCAODeSsVrwwvcJOaoN0LIUIaFVNZzmWyNfXas=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg=
|
||||
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/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
|
||||
github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s=
|
||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
|
||||
github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU=
|
||||
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
|
||||
github.com/prometheus/client_golang v1.11.1/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
|
||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4=
|
||||
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
|
||||
github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
|
||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
|
||||
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
|
||||
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
||||
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||
github.com/sagikazarmark/crypt v0.6.0/go.mod h1:U8+INwJo3nBv1m6A/8OBXAq7Jnpspk5AxSgDyEQcea8=
|
||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
||||
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/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/spf13/afero v1.8.2/go.mod h1:CtAatgMJh6bJEIs48Ay/FOnkljP3WeGUG0MC1RfAqwo=
|
||||
github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU=
|
||||
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/viper v1.13.0/go.mod h1:Icm2xNL3/8uyh/wFuB1jI7TiTNKp8632Nwegu+zgdYw=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/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/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
|
||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
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.5/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
github.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0=
|
||||
github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
|
||||
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.69.0 h1:fNLLESD2SooWeh2cidsuFtOcrEi4uB4m1mPrkJMZyVI=
|
||||
github.com/valyala/fasthttp v1.69.0/go.mod h1:4wA4PfAraPlAsJ5jMSqCE2ug5tqUPwKXxVj8oNECGcw=
|
||||
github.com/valyala/fastjson v1.6.10 h1:/yjJg8jaVQdYR3arGxPE2X5z89xrlhS0eGXdv+ADTh4=
|
||||
github.com/valyala/fastjson v1.6.10/go.mod h1:e6FubmQouUNP73jtMLmcbxS6ydWIpOfhz34TSfO3JaE=
|
||||
github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU=
|
||||
github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E=
|
||||
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
go.etcd.io/etcd/api/v3 v3.5.4/go.mod h1:5GB2vv4A4AOn3yk7MftYGHkUfGtDHnEraIjym4dYz5A=
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.5.4/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
|
||||
go.etcd.io/etcd/client/v2 v2.305.4/go.mod h1:Ud+VUwIi9/uQHOMA+4ekToJ12lTxlv0zB/+DHwTGEbU=
|
||||
go.etcd.io/etcd/client/v3 v3.5.4/go.mod h1:ZaRkVgBZC+L+dLCjTcF1hRXpgZXQPOvnA/Ak/gq3kiY=
|
||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||
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.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
|
||||
go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
|
||||
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
|
||||
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||
go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y=
|
||||
go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU=
|
||||
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
|
||||
go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
|
||||
golang.org/x/arch v0.0.0-20210923205945-b76863e36670 h1:18EFjUmQOcUvxNYSkA6jO9VAiXCnxFY6NyDX0bHDmkU=
|
||||
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
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=
|
||||
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||
golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
|
||||
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
|
||||
golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||
golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
|
||||
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
|
||||
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
||||
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
|
||||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
|
||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
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-20181114220301-adae6a3d119a/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=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
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-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=
|
||||
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8=
|
||||
golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
|
||||
golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
|
||||
golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220513210516-0976fa681c29/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/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-20190222072716-a9d3bda3a223/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=
|
||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
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-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/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-20200124204421-9fbb57f87de9/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=
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
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-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-20200625212154-ddb9806d33ae/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=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/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-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211210111614-af8b64212486/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-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220209214540-3681064d5158/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-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk=
|
||||
golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
|
||||
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
|
||||
golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
|
||||
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
|
||||
golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
|
||||
golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
||||
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
|
||||
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
||||
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
|
||||
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
|
||||
google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
|
||||
google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
||||
google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
||||
google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
||||
google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
|
||||
google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
|
||||
google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
|
||||
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
|
||||
google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=
|
||||
google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE=
|
||||
google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8=
|
||||
google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU=
|
||||
google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94=
|
||||
google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo=
|
||||
google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4=
|
||||
google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw=
|
||||
google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU=
|
||||
google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k=
|
||||
google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE=
|
||||
google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE=
|
||||
google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI=
|
||||
google.golang.org/api v0.59.0/go.mod h1:sT2boj7M9YJxZzgeZqXogmhfmRWDtPzT31xkieUbuZU=
|
||||
google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I=
|
||||
google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo=
|
||||
google.golang.org/api v0.67.0/go.mod h1:ShHKP8E60yPsKNw/w8w+VYaj9H6buA5UqDp8dhbQZ6g=
|
||||
google.golang.org/api v0.70.0/go.mod h1:Bs4ZM2HGifEvXwd50TtW70ovgJffJYw2oRCOFU/SkfA=
|
||||
google.golang.org/api v0.71.0/go.mod h1:4PyU6e6JogV1f9eA4voyrTY2batOLdgZ5qZ5HOCc4j8=
|
||||
google.golang.org/api v0.74.0/go.mod h1:ZpfMZOVRMywNyvJFeqL9HRWBgAuRfSjJFpe9QtRRyDs=
|
||||
google.golang.org/api v0.75.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA=
|
||||
google.golang.org/api v0.78.0/go.mod h1:1Sg78yoMLOhlQTeF+ARBoytAcH1NNyyl390YMy6rKmw=
|
||||
google.golang.org/api v0.81.0/go.mod h1:FA6Mb/bZxj706H2j+j2d6mHEEaHBmbbWnkfvmorOCko=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
|
||||
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
|
||||
google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
|
||||
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
|
||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||
google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
|
||||
google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A=
|
||||
google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A=
|
||||
google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
|
||||
google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
|
||||
google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
|
||||
google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24=
|
||||
google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k=
|
||||
google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k=
|
||||
google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48=
|
||||
google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48=
|
||||
google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w=
|
||||
google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
|
||||
google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
|
||||
google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
|
||||
google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
|
||||
google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
|
||||
google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||
google.golang.org/genproto v0.0.0-20211008145708-270636b82663/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||
google.golang.org/genproto v0.0.0-20211028162531-8db9c33dc351/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||
google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||
google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||
google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||
google.golang.org/genproto v0.0.0-20211221195035-429b39de9b1c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||
google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||
google.golang.org/genproto v0.0.0-20220207164111-0872dc986b00/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||
google.golang.org/genproto v0.0.0-20220218161850-94dd64e39d7c/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
|
||||
google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
|
||||
google.golang.org/genproto v0.0.0-20220304144024-325a89244dc8/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
|
||||
google.golang.org/genproto v0.0.0-20220310185008-1973136f34c6/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
|
||||
google.golang.org/genproto v0.0.0-20220324131243-acbaeb5b85eb/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E=
|
||||
google.golang.org/genproto v0.0.0-20220407144326-9054f6ed7bac/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
|
||||
google.golang.org/genproto v0.0.0-20220413183235-5e96e2839df9/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
|
||||
google.golang.org/genproto v0.0.0-20220414192740-2d67ff6cf2b4/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
|
||||
google.golang.org/genproto v0.0.0-20220421151946-72621c1f0bd3/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
|
||||
google.golang.org/genproto v0.0.0-20220429170224-98d788798c3e/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
|
||||
google.golang.org/genproto v0.0.0-20220505152158-f39f71e6c8f3/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
|
||||
google.golang.org/genproto v0.0.0-20220519153652-3a47de7e79bd/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
||||
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
|
||||
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
|
||||
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||
google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
|
||||
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
|
||||
google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
|
||||
google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||
google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||
google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
|
||||
google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
|
||||
google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
|
||||
google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
|
||||
google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
|
||||
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
|
||||
google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
|
||||
google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
|
||||
google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ=
|
||||
google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
|
||||
google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
|
||||
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
|
||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
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/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/telebot.v3 v3.3.8 h1:uVDGjak9l824FN9YARWUHMsiNZnlohAVwUycw21k6t8=
|
||||
gopkg.in/telebot.v3 v3.3.8/go.mod h1:1mlbqcLTVSfK9dx7fdp+Nb5HZsy4LLPtpZTKmwhwtzM=
|
||||
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.3/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/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/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/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=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
||||
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
|
||||
@@ -0,0 +1,75 @@
|
||||
goos: darwin
|
||||
goarch: arm64
|
||||
pkg: github.com/lukaszraczylo/go-telegram/test/benchmarks
|
||||
cpu: Apple M4 Max
|
||||
│ /Users/nvm/Documents/projects/private/go-telegram/test/benchmarks/results/raw.txt │
|
||||
│ sec/op │
|
||||
Call_ours-16 38.95µ ± 3%
|
||||
Call_gotba-16 41.95µ ± 2%
|
||||
Call_telebot-16 43.63µ ± 0%
|
||||
Call_gobot-16 61.11µ ± 1%
|
||||
Call_telego-16 36.31µ ± 1%
|
||||
Dispatch_ours-16 100.7n ± 3%
|
||||
Dispatch_telebot-16 269.2n ± 5%
|
||||
Dispatch_gobot-16 251.5n ± 4%
|
||||
LargeUnmarshal_ours-16 6.667µ ± 4%
|
||||
LargeUnmarshal_gotba-16 8.321µ ± 2%
|
||||
LargeUnmarshal_telebot-16 10.24µ ± 4%
|
||||
LargeUnmarshal_gobot-16 8.150µ ± 2%
|
||||
LargeUnmarshal_telego-16 7.797µ ± 1%
|
||||
LargeUnmarshal_echotron-16 8.072µ ± 0%
|
||||
Webhook_ours-16 1.743µ ± 3%
|
||||
Webhook_gotba-16 2.016µ ± 3%
|
||||
Webhook_telebot-16 2.073µ ± 3%
|
||||
Webhook_gobot-16 1.999µ ± 1%
|
||||
Webhook_telego-16 2.026µ ± 2%
|
||||
Webhook_echotron-16 1.973µ ± 0%
|
||||
geomean 4.603µ
|
||||
|
||||
│ /Users/nvm/Documents/projects/private/go-telegram/test/benchmarks/results/raw.txt │
|
||||
│ B/op │
|
||||
Call_ours-16 11.17Ki ± 0%
|
||||
Call_gotba-16 10.95Ki ± 0%
|
||||
Call_telebot-16 13.16Ki ± 0%
|
||||
Call_gobot-16 13.51Ki ± 0%
|
||||
Call_telego-16 6.556Ki ± 0%
|
||||
Dispatch_ours-16 128.0 ± 0%
|
||||
Dispatch_telebot-16 678.0 ± 0%
|
||||
Dispatch_gobot-16 48.00 ± 0%
|
||||
LargeUnmarshal_ours-16 5.881Ki ± 0%
|
||||
LargeUnmarshal_gotba-16 3.438Ki ± 0%
|
||||
LargeUnmarshal_telebot-16 5.594Ki ± 0%
|
||||
LargeUnmarshal_gobot-16 4.703Ki ± 0%
|
||||
LargeUnmarshal_telego-16 6.621Ki ± 0%
|
||||
LargeUnmarshal_echotron-16 4.219Ki ± 0%
|
||||
Webhook_ours-16 2.180Ki ± 0%
|
||||
Webhook_gotba-16 1.461Ki ± 0%
|
||||
Webhook_telebot-16 1.773Ki ± 0%
|
||||
Webhook_gobot-16 1.789Ki ± 0%
|
||||
Webhook_telego-16 3.060Ki ± 0%
|
||||
Webhook_echotron-16 1.680Ki ± 0%
|
||||
geomean 2.701Ki
|
||||
|
||||
│ /Users/nvm/Documents/projects/private/go-telegram/test/benchmarks/results/raw.txt │
|
||||
│ allocs/op │
|
||||
Call_ours-16 104.0 ± 0%
|
||||
Call_gotba-16 125.0 ± 0%
|
||||
Call_telebot-16 139.0 ± 0%
|
||||
Call_gobot-16 176.0 ± 0%
|
||||
Call_telego-16 48.00 ± 0%
|
||||
Dispatch_ours-16 3.000 ± 0%
|
||||
Dispatch_telebot-16 5.000 ± 0%
|
||||
Dispatch_gobot-16 1.000 ± 0%
|
||||
LargeUnmarshal_ours-16 34.00 ± 0%
|
||||
LargeUnmarshal_gotba-16 56.00 ± 0%
|
||||
LargeUnmarshal_telebot-16 60.00 ± 0%
|
||||
LargeUnmarshal_gobot-16 50.00 ± 0%
|
||||
LargeUnmarshal_telego-16 31.00 ± 0%
|
||||
LargeUnmarshal_echotron-16 56.00 ± 0%
|
||||
Webhook_ours-16 11.00 ± 0%
|
||||
Webhook_gotba-16 17.00 ± 0%
|
||||
Webhook_telebot-16 17.00 ± 0%
|
||||
Webhook_gobot-16 16.00 ± 0%
|
||||
Webhook_telego-16 11.00 ± 0%
|
||||
Webhook_echotron-16 16.00 ± 0%
|
||||
geomean 26.03
|
||||
@@ -0,0 +1,207 @@
|
||||
goos: darwin
|
||||
goarch: arm64
|
||||
pkg: github.com/lukaszraczylo/go-telegram/test/benchmarks
|
||||
cpu: Apple M4 Max
|
||||
BenchmarkCall_ours-16 30754 38732 ns/op 11589 B/op 105 allocs/op
|
||||
BenchmarkCall_ours-16 31054 39002 ns/op 11476 B/op 104 allocs/op
|
||||
BenchmarkCall_ours-16 30990 38440 ns/op 11471 B/op 104 allocs/op
|
||||
BenchmarkCall_ours-16 30301 39464 ns/op 11452 B/op 104 allocs/op
|
||||
BenchmarkCall_ours-16 30438 38897 ns/op 11425 B/op 104 allocs/op
|
||||
BenchmarkCall_ours-16 30783 39107 ns/op 11429 B/op 104 allocs/op
|
||||
BenchmarkCall_ours-16 30486 39507 ns/op 11402 B/op 104 allocs/op
|
||||
BenchmarkCall_ours-16 30045 37723 ns/op 11442 B/op 104 allocs/op
|
||||
BenchmarkCall_ours-16 37867 33103 ns/op 11444 B/op 104 allocs/op
|
||||
BenchmarkCall_ours-16 30522 39139 ns/op 11436 B/op 104 allocs/op
|
||||
BenchmarkCall_gotba-16 29838 40947 ns/op 11243 B/op 125 allocs/op
|
||||
BenchmarkCall_gotba-16 28545 41897 ns/op 11182 B/op 125 allocs/op
|
||||
BenchmarkCall_gotba-16 28713 41146 ns/op 11197 B/op 125 allocs/op
|
||||
BenchmarkCall_gotba-16 28480 42210 ns/op 11238 B/op 125 allocs/op
|
||||
BenchmarkCall_gotba-16 28831 42004 ns/op 11204 B/op 125 allocs/op
|
||||
BenchmarkCall_gotba-16 28484 42012 ns/op 11224 B/op 125 allocs/op
|
||||
BenchmarkCall_gotba-16 30481 41283 ns/op 11212 B/op 125 allocs/op
|
||||
BenchmarkCall_gotba-16 28646 42042 ns/op 11209 B/op 125 allocs/op
|
||||
BenchmarkCall_gotba-16 28418 40680 ns/op 11250 B/op 125 allocs/op
|
||||
BenchmarkCall_gotba-16 28358 42146 ns/op 11208 B/op 125 allocs/op
|
||||
BenchmarkCall_telebot-16 27294 43739 ns/op 13522 B/op 139 allocs/op
|
||||
BenchmarkCall_telebot-16 27763 43429 ns/op 13491 B/op 139 allocs/op
|
||||
BenchmarkCall_telebot-16 27525 43618 ns/op 13478 B/op 139 allocs/op
|
||||
BenchmarkCall_telebot-16 27423 43711 ns/op 13431 B/op 139 allocs/op
|
||||
BenchmarkCall_telebot-16 27415 43704 ns/op 13473 B/op 139 allocs/op
|
||||
BenchmarkCall_telebot-16 27268 43834 ns/op 13477 B/op 139 allocs/op
|
||||
BenchmarkCall_telebot-16 28180 43488 ns/op 13486 B/op 139 allocs/op
|
||||
BenchmarkCall_telebot-16 27480 43644 ns/op 13485 B/op 139 allocs/op
|
||||
BenchmarkCall_telebot-16 27458 43581 ns/op 13479 B/op 139 allocs/op
|
||||
BenchmarkCall_telebot-16 27949 43415 ns/op 13480 B/op 139 allocs/op
|
||||
BenchmarkCall_gobot-16 19503 60924 ns/op 13847 B/op 176 allocs/op
|
||||
BenchmarkCall_gobot-16 19620 61253 ns/op 13837 B/op 176 allocs/op
|
||||
BenchmarkCall_gobot-16 19790 60869 ns/op 13839 B/op 176 allocs/op
|
||||
BenchmarkCall_gobot-16 19574 61153 ns/op 13816 B/op 176 allocs/op
|
||||
BenchmarkCall_gobot-16 19634 61070 ns/op 13830 B/op 176 allocs/op
|
||||
BenchmarkCall_gobot-16 19569 61173 ns/op 13817 B/op 176 allocs/op
|
||||
BenchmarkCall_gobot-16 19549 61688 ns/op 13851 B/op 176 allocs/op
|
||||
BenchmarkCall_gobot-16 19918 60815 ns/op 13779 B/op 176 allocs/op
|
||||
BenchmarkCall_gobot-16 19440 61667 ns/op 13830 B/op 176 allocs/op
|
||||
BenchmarkCall_gobot-16 19660 61036 ns/op 13837 B/op 176 allocs/op
|
||||
BenchmarkCall_telego-16 32732 36606 ns/op 6788 B/op 48 allocs/op
|
||||
BenchmarkCall_telego-16 33837 35882 ns/op 6697 B/op 48 allocs/op
|
||||
BenchmarkCall_telego-16 33074 36146 ns/op 6693 B/op 48 allocs/op
|
||||
BenchmarkCall_telego-16 33400 36090 ns/op 6723 B/op 48 allocs/op
|
||||
BenchmarkCall_telego-16 32684 36296 ns/op 6709 B/op 48 allocs/op
|
||||
BenchmarkCall_telego-16 32926 36577 ns/op 6721 B/op 48 allocs/op
|
||||
BenchmarkCall_telego-16 33928 35481 ns/op 6708 B/op 48 allocs/op
|
||||
BenchmarkCall_telego-16 33195 36318 ns/op 6711 B/op 48 allocs/op
|
||||
BenchmarkCall_telego-16 33140 36812 ns/op 6717 B/op 48 allocs/op
|
||||
BenchmarkCall_telego-16 32343 37631 ns/op 6716 B/op 48 allocs/op
|
||||
BenchmarkDispatch_ours-16 12199088 98.57 ns/op 128 B/op 3 allocs/op
|
||||
BenchmarkDispatch_ours-16 12223122 97.66 ns/op 128 B/op 3 allocs/op
|
||||
BenchmarkDispatch_ours-16 12088142 97.43 ns/op 128 B/op 3 allocs/op
|
||||
BenchmarkDispatch_ours-16 12463010 100.9 ns/op 128 B/op 3 allocs/op
|
||||
BenchmarkDispatch_ours-16 12284848 99.38 ns/op 128 B/op 3 allocs/op
|
||||
BenchmarkDispatch_ours-16 11485198 101.1 ns/op 128 B/op 3 allocs/op
|
||||
BenchmarkDispatch_ours-16 11685897 102.2 ns/op 128 B/op 3 allocs/op
|
||||
BenchmarkDispatch_ours-16 11733669 102.1 ns/op 128 B/op 3 allocs/op
|
||||
BenchmarkDispatch_ours-16 11811807 100.5 ns/op 128 B/op 3 allocs/op
|
||||
BenchmarkDispatch_ours-16 11691974 103.1 ns/op 128 B/op 3 allocs/op
|
||||
BenchmarkDispatch_telebot-16 4270724 284.6 ns/op 679 B/op 5 allocs/op
|
||||
BenchmarkDispatch_telebot-16 4369950 270.2 ns/op 678 B/op 5 allocs/op
|
||||
BenchmarkDispatch_telebot-16 4604205 269.9 ns/op 679 B/op 5 allocs/op
|
||||
BenchmarkDispatch_telebot-16 4431572 282.2 ns/op 678 B/op 5 allocs/op
|
||||
BenchmarkDispatch_telebot-16 4186550 272.0 ns/op 678 B/op 5 allocs/op
|
||||
BenchmarkDispatch_telebot-16 4472223 265.7 ns/op 679 B/op 5 allocs/op
|
||||
BenchmarkDispatch_telebot-16 4537406 265.0 ns/op 679 B/op 5 allocs/op
|
||||
BenchmarkDispatch_telebot-16 4544478 264.4 ns/op 678 B/op 5 allocs/op
|
||||
BenchmarkDispatch_telebot-16 4519431 266.7 ns/op 678 B/op 5 allocs/op
|
||||
BenchmarkDispatch_telebot-16 4448779 268.5 ns/op 678 B/op 5 allocs/op
|
||||
BenchmarkDispatch_gobot-16 4493029 254.1 ns/op 48 B/op 1 allocs/op
|
||||
BenchmarkDispatch_gobot-16 4726080 261.5 ns/op 48 B/op 1 allocs/op
|
||||
BenchmarkDispatch_gobot-16 4884592 249.6 ns/op 48 B/op 1 allocs/op
|
||||
BenchmarkDispatch_gobot-16 4639986 256.7 ns/op 48 B/op 1 allocs/op
|
||||
BenchmarkDispatch_gobot-16 4424702 261.1 ns/op 48 B/op 1 allocs/op
|
||||
BenchmarkDispatch_gobot-16 4783779 249.2 ns/op 48 B/op 1 allocs/op
|
||||
BenchmarkDispatch_gobot-16 4916862 248.2 ns/op 48 B/op 1 allocs/op
|
||||
BenchmarkDispatch_gobot-16 4884650 249.9 ns/op 48 B/op 1 allocs/op
|
||||
BenchmarkDispatch_gobot-16 4822939 252.4 ns/op 48 B/op 1 allocs/op
|
||||
BenchmarkDispatch_gobot-16 4707606 250.5 ns/op 48 B/op 1 allocs/op
|
||||
BenchmarkLargeUnmarshal_ours-16 177442 6697 ns/op 6024 B/op 34 allocs/op
|
||||
BenchmarkLargeUnmarshal_ours-16 178348 6700 ns/op 6021 B/op 34 allocs/op
|
||||
BenchmarkLargeUnmarshal_ours-16 180528 6686 ns/op 6022 B/op 34 allocs/op
|
||||
BenchmarkLargeUnmarshal_ours-16 182416 6659 ns/op 6021 B/op 34 allocs/op
|
||||
BenchmarkLargeUnmarshal_ours-16 179305 6675 ns/op 6022 B/op 34 allocs/op
|
||||
BenchmarkLargeUnmarshal_ours-16 176892 6724 ns/op 6021 B/op 34 allocs/op
|
||||
BenchmarkLargeUnmarshal_ours-16 185355 6392 ns/op 6022 B/op 34 allocs/op
|
||||
BenchmarkLargeUnmarshal_ours-16 189590 6390 ns/op 6022 B/op 34 allocs/op
|
||||
BenchmarkLargeUnmarshal_ours-16 189783 6438 ns/op 6022 B/op 34 allocs/op
|
||||
BenchmarkLargeUnmarshal_ours-16 187572 6483 ns/op 6022 B/op 34 allocs/op
|
||||
BenchmarkLargeUnmarshal_gotba-16 142377 8296 ns/op 3520 B/op 56 allocs/op
|
||||
BenchmarkLargeUnmarshal_gotba-16 144884 8274 ns/op 3520 B/op 56 allocs/op
|
||||
BenchmarkLargeUnmarshal_gotba-16 146434 8295 ns/op 3520 B/op 56 allocs/op
|
||||
BenchmarkLargeUnmarshal_gotba-16 145183 8260 ns/op 3520 B/op 56 allocs/op
|
||||
BenchmarkLargeUnmarshal_gotba-16 144775 8416 ns/op 3520 B/op 56 allocs/op
|
||||
BenchmarkLargeUnmarshal_gotba-16 139510 8224 ns/op 3520 B/op 56 allocs/op
|
||||
BenchmarkLargeUnmarshal_gotba-16 146359 8542 ns/op 3520 B/op 56 allocs/op
|
||||
BenchmarkLargeUnmarshal_gotba-16 144981 8346 ns/op 3520 B/op 56 allocs/op
|
||||
BenchmarkLargeUnmarshal_gotba-16 146877 8399 ns/op 3520 B/op 56 allocs/op
|
||||
BenchmarkLargeUnmarshal_gotba-16 145443 8454 ns/op 3519 B/op 56 allocs/op
|
||||
BenchmarkLargeUnmarshal_telebot-16 116883 10327 ns/op 5728 B/op 60 allocs/op
|
||||
BenchmarkLargeUnmarshal_telebot-16 114584 10333 ns/op 5728 B/op 60 allocs/op
|
||||
BenchmarkLargeUnmarshal_telebot-16 117277 10250 ns/op 5728 B/op 60 allocs/op
|
||||
BenchmarkLargeUnmarshal_telebot-16 117700 10270 ns/op 5728 B/op 60 allocs/op
|
||||
BenchmarkLargeUnmarshal_telebot-16 117328 10401 ns/op 5728 B/op 60 allocs/op
|
||||
BenchmarkLargeUnmarshal_telebot-16 115922 10223 ns/op 5728 B/op 60 allocs/op
|
||||
BenchmarkLargeUnmarshal_telebot-16 117475 10049 ns/op 5728 B/op 60 allocs/op
|
||||
BenchmarkLargeUnmarshal_telebot-16 123367 9866 ns/op 5728 B/op 60 allocs/op
|
||||
BenchmarkLargeUnmarshal_telebot-16 123385 9811 ns/op 5728 B/op 60 allocs/op
|
||||
BenchmarkLargeUnmarshal_telebot-16 122586 9873 ns/op 5728 B/op 60 allocs/op
|
||||
BenchmarkLargeUnmarshal_gobot-16 148576 8064 ns/op 4817 B/op 50 allocs/op
|
||||
BenchmarkLargeUnmarshal_gobot-16 147967 8113 ns/op 4816 B/op 50 allocs/op
|
||||
BenchmarkLargeUnmarshal_gobot-16 150718 7991 ns/op 4816 B/op 50 allocs/op
|
||||
BenchmarkLargeUnmarshal_gobot-16 150271 8066 ns/op 4815 B/op 50 allocs/op
|
||||
BenchmarkLargeUnmarshal_gobot-16 147646 8066 ns/op 4816 B/op 50 allocs/op
|
||||
BenchmarkLargeUnmarshal_gobot-16 147889 8186 ns/op 4816 B/op 50 allocs/op
|
||||
BenchmarkLargeUnmarshal_gobot-16 143164 8413 ns/op 4816 B/op 50 allocs/op
|
||||
BenchmarkLargeUnmarshal_gobot-16 150464 8276 ns/op 4815 B/op 50 allocs/op
|
||||
BenchmarkLargeUnmarshal_gobot-16 145249 8201 ns/op 4816 B/op 50 allocs/op
|
||||
BenchmarkLargeUnmarshal_gobot-16 146100 8216 ns/op 4816 B/op 50 allocs/op
|
||||
BenchmarkLargeUnmarshal_telego-16 149001 7802 ns/op 6781 B/op 31 allocs/op
|
||||
BenchmarkLargeUnmarshal_telego-16 152780 7835 ns/op 6775 B/op 31 allocs/op
|
||||
BenchmarkLargeUnmarshal_telego-16 156508 7817 ns/op 6780 B/op 31 allocs/op
|
||||
BenchmarkLargeUnmarshal_telego-16 154938 7816 ns/op 6777 B/op 31 allocs/op
|
||||
BenchmarkLargeUnmarshal_telego-16 150121 7809 ns/op 6778 B/op 31 allocs/op
|
||||
BenchmarkLargeUnmarshal_telego-16 152810 7791 ns/op 6780 B/op 31 allocs/op
|
||||
BenchmarkLargeUnmarshal_telego-16 159613 7784 ns/op 6778 B/op 31 allocs/op
|
||||
BenchmarkLargeUnmarshal_telego-16 154402 7729 ns/op 6780 B/op 31 allocs/op
|
||||
BenchmarkLargeUnmarshal_telego-16 157184 7660 ns/op 6782 B/op 31 allocs/op
|
||||
BenchmarkLargeUnmarshal_telego-16 155822 7768 ns/op 6780 B/op 31 allocs/op
|
||||
BenchmarkLargeUnmarshal_echotron-16 144252 8147 ns/op 4323 B/op 56 allocs/op
|
||||
BenchmarkLargeUnmarshal_echotron-16 147961 8089 ns/op 4319 B/op 56 allocs/op
|
||||
BenchmarkLargeUnmarshal_echotron-16 149847 8049 ns/op 4320 B/op 56 allocs/op
|
||||
BenchmarkLargeUnmarshal_echotron-16 149128 8069 ns/op 4320 B/op 56 allocs/op
|
||||
BenchmarkLargeUnmarshal_echotron-16 147277 8075 ns/op 4320 B/op 56 allocs/op
|
||||
BenchmarkLargeUnmarshal_echotron-16 149132 8089 ns/op 4320 B/op 56 allocs/op
|
||||
BenchmarkLargeUnmarshal_echotron-16 148837 8014 ns/op 4319 B/op 56 allocs/op
|
||||
BenchmarkLargeUnmarshal_echotron-16 149288 8050 ns/op 4320 B/op 56 allocs/op
|
||||
BenchmarkLargeUnmarshal_echotron-16 146833 8097 ns/op 4320 B/op 56 allocs/op
|
||||
BenchmarkLargeUnmarshal_echotron-16 149233 8041 ns/op 4320 B/op 56 allocs/op
|
||||
BenchmarkWebhook_ours-16 707102 1721 ns/op 2232 B/op 11 allocs/op
|
||||
BenchmarkWebhook_ours-16 700047 1734 ns/op 2232 B/op 11 allocs/op
|
||||
BenchmarkWebhook_ours-16 725071 1721 ns/op 2232 B/op 11 allocs/op
|
||||
BenchmarkWebhook_ours-16 675003 1751 ns/op 2232 B/op 11 allocs/op
|
||||
BenchmarkWebhook_ours-16 693903 1787 ns/op 2232 B/op 11 allocs/op
|
||||
BenchmarkWebhook_ours-16 714036 1751 ns/op 2232 B/op 11 allocs/op
|
||||
BenchmarkWebhook_ours-16 646494 1816 ns/op 2232 B/op 11 allocs/op
|
||||
BenchmarkWebhook_ours-16 696355 1801 ns/op 2232 B/op 11 allocs/op
|
||||
BenchmarkWebhook_ours-16 709545 1734 ns/op 2232 B/op 11 allocs/op
|
||||
BenchmarkWebhook_ours-16 709700 1725 ns/op 2232 B/op 11 allocs/op
|
||||
BenchmarkWebhook_gotba-16 611132 2027 ns/op 1496 B/op 17 allocs/op
|
||||
BenchmarkWebhook_gotba-16 624046 2072 ns/op 1496 B/op 17 allocs/op
|
||||
BenchmarkWebhook_gotba-16 588478 2093 ns/op 1496 B/op 17 allocs/op
|
||||
BenchmarkWebhook_gotba-16 609744 2012 ns/op 1496 B/op 17 allocs/op
|
||||
BenchmarkWebhook_gotba-16 606912 2012 ns/op 1496 B/op 17 allocs/op
|
||||
BenchmarkWebhook_gotba-16 612211 2000 ns/op 1496 B/op 17 allocs/op
|
||||
BenchmarkWebhook_gotba-16 605488 2015 ns/op 1496 B/op 17 allocs/op
|
||||
BenchmarkWebhook_gotba-16 622398 2006 ns/op 1496 B/op 17 allocs/op
|
||||
BenchmarkWebhook_gotba-16 610478 2017 ns/op 1496 B/op 17 allocs/op
|
||||
BenchmarkWebhook_gotba-16 610350 2030 ns/op 1496 B/op 17 allocs/op
|
||||
BenchmarkWebhook_telebot-16 559515 2138 ns/op 1816 B/op 17 allocs/op
|
||||
BenchmarkWebhook_telebot-16 558510 2057 ns/op 1816 B/op 17 allocs/op
|
||||
BenchmarkWebhook_telebot-16 587257 2079 ns/op 1816 B/op 17 allocs/op
|
||||
BenchmarkWebhook_telebot-16 585321 2059 ns/op 1816 B/op 17 allocs/op
|
||||
BenchmarkWebhook_telebot-16 576236 2067 ns/op 1816 B/op 17 allocs/op
|
||||
BenchmarkWebhook_telebot-16 570172 2070 ns/op 1816 B/op 17 allocs/op
|
||||
BenchmarkWebhook_telebot-16 568270 2131 ns/op 1816 B/op 17 allocs/op
|
||||
BenchmarkWebhook_telebot-16 567567 2094 ns/op 1816 B/op 17 allocs/op
|
||||
BenchmarkWebhook_telebot-16 586588 2076 ns/op 1816 B/op 17 allocs/op
|
||||
BenchmarkWebhook_telebot-16 574495 2062 ns/op 1816 B/op 17 allocs/op
|
||||
BenchmarkWebhook_gobot-16 597710 2006 ns/op 1832 B/op 16 allocs/op
|
||||
BenchmarkWebhook_gobot-16 594742 2016 ns/op 1832 B/op 16 allocs/op
|
||||
BenchmarkWebhook_gobot-16 603187 1998 ns/op 1832 B/op 16 allocs/op
|
||||
BenchmarkWebhook_gobot-16 608301 2011 ns/op 1832 B/op 16 allocs/op
|
||||
BenchmarkWebhook_gobot-16 605532 1984 ns/op 1832 B/op 16 allocs/op
|
||||
BenchmarkWebhook_gobot-16 609892 1990 ns/op 1832 B/op 16 allocs/op
|
||||
BenchmarkWebhook_gobot-16 596637 1999 ns/op 1832 B/op 16 allocs/op
|
||||
BenchmarkWebhook_gobot-16 592108 1993 ns/op 1832 B/op 16 allocs/op
|
||||
BenchmarkWebhook_gobot-16 607069 1999 ns/op 1832 B/op 16 allocs/op
|
||||
BenchmarkWebhook_gobot-16 594915 1997 ns/op 1832 B/op 16 allocs/op
|
||||
BenchmarkWebhook_telego-16 603300 2021 ns/op 3133 B/op 11 allocs/op
|
||||
BenchmarkWebhook_telego-16 602503 2016 ns/op 3133 B/op 11 allocs/op
|
||||
BenchmarkWebhook_telego-16 618267 2016 ns/op 3133 B/op 11 allocs/op
|
||||
BenchmarkWebhook_telego-16 601855 2027 ns/op 3133 B/op 11 allocs/op
|
||||
BenchmarkWebhook_telego-16 612424 2035 ns/op 3132 B/op 11 allocs/op
|
||||
BenchmarkWebhook_telego-16 595890 2074 ns/op 3133 B/op 11 allocs/op
|
||||
BenchmarkWebhook_telego-16 605565 2001 ns/op 3133 B/op 11 allocs/op
|
||||
BenchmarkWebhook_telego-16 610453 2096 ns/op 3133 B/op 11 allocs/op
|
||||
BenchmarkWebhook_telego-16 588056 2069 ns/op 3132 B/op 11 allocs/op
|
||||
BenchmarkWebhook_telego-16 595764 2025 ns/op 3133 B/op 11 allocs/op
|
||||
BenchmarkWebhook_echotron-16 599088 1975 ns/op 1720 B/op 16 allocs/op
|
||||
BenchmarkWebhook_echotron-16 626964 1975 ns/op 1720 B/op 16 allocs/op
|
||||
BenchmarkWebhook_echotron-16 635306 1967 ns/op 1720 B/op 16 allocs/op
|
||||
BenchmarkWebhook_echotron-16 606621 1965 ns/op 1720 B/op 16 allocs/op
|
||||
BenchmarkWebhook_echotron-16 625998 1965 ns/op 1720 B/op 16 allocs/op
|
||||
BenchmarkWebhook_echotron-16 646352 1976 ns/op 1720 B/op 16 allocs/op
|
||||
BenchmarkWebhook_echotron-16 634186 1971 ns/op 1720 B/op 16 allocs/op
|
||||
BenchmarkWebhook_echotron-16 628503 1982 ns/op 1720 B/op 16 allocs/op
|
||||
BenchmarkWebhook_echotron-16 612586 1975 ns/op 1720 B/op 16 allocs/op
|
||||
BenchmarkWebhook_echotron-16 622320 1965 ns/op 1720 B/op 16 allocs/op
|
||||
PASS
|
||||
ok github.com/lukaszraczylo/go-telegram/test/benchmarks 241.963s
|
||||
? github.com/lukaszraczylo/go-telegram/test/benchmarks/shared [no test files]
|
||||
@@ -0,0 +1,85 @@
|
||||
// Package shared holds JSON fixtures and an httptest mock server reused by
|
||||
// every per-library benchmark. Keeping fixtures here guarantees that all
|
||||
// libraries decode the same bytes and that round-trip benches hit the same
|
||||
// canned response.
|
||||
package shared
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// SmallUpdateJSON is a minimal text-message update — what a typical bot sees
|
||||
// most often. Used by the dispatcher and webhook benches.
|
||||
const SmallUpdateJSON = `{
|
||||
"update_id": 123456789,
|
||||
"message": {
|
||||
"message_id": 1,
|
||||
"date": 1715000000,
|
||||
"chat": {"id": 42, "type": "private", "first_name": "Alice"},
|
||||
"from": {"id": 42, "is_bot": false, "first_name": "Alice", "language_code": "en"},
|
||||
"text": "/start"
|
||||
}
|
||||
}`
|
||||
|
||||
// LargeUpdateJSON exercises union/discriminator decoding: text + entities,
|
||||
// reply markup with an inline keyboard, and a 3-size photo array.
|
||||
const LargeUpdateJSON = `{
|
||||
"update_id": 987654321,
|
||||
"message": {
|
||||
"message_id": 17,
|
||||
"date": 1715000123,
|
||||
"chat": {"id": -100123456789, "type": "supergroup", "title": "Devs"},
|
||||
"from": {"id": 42, "is_bot": false, "first_name": "Alice", "username": "alice"},
|
||||
"text": "see https://example.com and @bob too",
|
||||
"entities": [
|
||||
{"type": "url", "offset": 4, "length": 19},
|
||||
{"type": "mention", "offset": 28, "length": 4},
|
||||
{"type": "bold", "offset": 0, "length": 3}
|
||||
],
|
||||
"reply_markup": {
|
||||
"inline_keyboard": [
|
||||
[{"text": "ok", "callback_data": "ok:1"}, {"text": "no", "callback_data": "no:1"}, {"text": "more", "callback_data": "more:1"}],
|
||||
[{"text": "left", "callback_data": "p:l"}, {"text": "right", "callback_data": "p:r"}]
|
||||
]
|
||||
},
|
||||
"photo": [
|
||||
{"file_id": "AgAD1", "file_unique_id": "u1", "width": 90, "height": 67, "file_size": 1234},
|
||||
{"file_id": "AgAD2", "file_unique_id": "u2", "width": 320, "height": 240, "file_size": 12345},
|
||||
{"file_id": "AgAD3", "file_unique_id": "u3", "width": 800, "height": 600, "file_size": 123456}
|
||||
]
|
||||
}
|
||||
}`
|
||||
|
||||
// SendMessageOKResponse is the canned `{"ok":true,"result":Message}` body
|
||||
// returned by the mock server for SendMessage round-trips.
|
||||
const SendMessageOKResponse = `{"ok":true,"result":{"message_id":1,"date":1715000000,"chat":{"id":42,"type":"private","first_name":"Alice"},"from":{"id":7,"is_bot":true,"first_name":"Bot","username":"benchbot"},"text":"hello"}}`
|
||||
|
||||
// GetMeOKResponse is the canned getMe reply some libraries call eagerly during
|
||||
// constructor (telebot, echotron). Lets us avoid a real network hop in setup.
|
||||
const GetMeOKResponse = `{"ok":true,"result":{"id":7,"is_bot":true,"first_name":"Bot","username":"benchbot","can_join_groups":true,"can_read_all_group_messages":false,"supports_inline_queries":false}}`
|
||||
|
||||
// NewMockServer returns an httptest.Server that responds to every Bot API
|
||||
// path with a canned `ok:true` body chosen by suffix:
|
||||
// - /sendMessage → SendMessageOKResponse
|
||||
// - /getMe → GetMeOKResponse
|
||||
// - anything else → SendMessageOKResponse (safe default for benches)
|
||||
//
|
||||
// Caller is responsible for Close().
|
||||
func NewMockServer() *httptest.Server {
|
||||
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
// Drain body so the client sees a complete request/response cycle.
|
||||
_, _ = io.Copy(io.Discard, r.Body)
|
||||
_ = r.Body.Close()
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
switch {
|
||||
case strings.HasSuffix(r.URL.Path, "/getMe"):
|
||||
_, _ = io.WriteString(w, GetMeOKResponse)
|
||||
default:
|
||||
_, _ = io.WriteString(w, SendMessageOKResponse)
|
||||
}
|
||||
})
|
||||
return httptest.NewServer(handler)
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
// Large-Update unmarshal benchmarks: decode a realistic Update with text +
|
||||
// entities + a 2x3 inline keyboard + a 3-size photo array. Stresses each
|
||||
// library's union/discriminator decoding (entities, reply markup variants).
|
||||
package benchmarks
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
"github.com/lukaszraczylo/go-telegram/api"
|
||||
"github.com/lukaszraczylo/go-telegram/test/benchmarks/shared"
|
||||
|
||||
echotron "github.com/NicoNex/echotron/v3"
|
||||
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
|
||||
gobotmodels "github.com/go-telegram/bot/models"
|
||||
telego "github.com/mymmrac/telego"
|
||||
tele "gopkg.in/telebot.v3"
|
||||
)
|
||||
|
||||
var largeUpdateBytes = []byte(shared.LargeUpdateJSON)
|
||||
|
||||
func BenchmarkLargeUnmarshal_ours(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
for b.Loop() {
|
||||
var u api.Update
|
||||
if err := json.Unmarshal(largeUpdateBytes, &u); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkLargeUnmarshal_gotba(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
for b.Loop() {
|
||||
var u tgbotapi.Update
|
||||
if err := json.Unmarshal(largeUpdateBytes, &u); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkLargeUnmarshal_telebot(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
for b.Loop() {
|
||||
var u tele.Update
|
||||
if err := json.Unmarshal(largeUpdateBytes, &u); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkLargeUnmarshal_gobot(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
for b.Loop() {
|
||||
var u gobotmodels.Update
|
||||
if err := json.Unmarshal(largeUpdateBytes, &u); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkLargeUnmarshal_telego(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
for b.Loop() {
|
||||
var u telego.Update
|
||||
if err := json.Unmarshal(largeUpdateBytes, &u); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkLargeUnmarshal_echotron(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
for b.Loop() {
|
||||
var u echotron.Update
|
||||
if err := json.Unmarshal(largeUpdateBytes, &u); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
// Webhook decode benchmarks: parse a small text-message Update from a fixed
|
||||
// JSON payload using each library's typed Update struct. Pure CPU — no
|
||||
// network. Stresses the JSON codec each library ships with by default.
|
||||
package benchmarks
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
"github.com/lukaszraczylo/go-telegram/api"
|
||||
"github.com/lukaszraczylo/go-telegram/test/benchmarks/shared"
|
||||
|
||||
echotron "github.com/NicoNex/echotron/v3"
|
||||
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
|
||||
gobotmodels "github.com/go-telegram/bot/models"
|
||||
telego "github.com/mymmrac/telego"
|
||||
tele "gopkg.in/telebot.v3"
|
||||
)
|
||||
|
||||
var smallUpdateBytes = []byte(shared.SmallUpdateJSON)
|
||||
|
||||
func BenchmarkWebhook_ours(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
for b.Loop() {
|
||||
var u api.Update
|
||||
if err := json.Unmarshal(smallUpdateBytes, &u); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkWebhook_gotba(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
for b.Loop() {
|
||||
var u tgbotapi.Update
|
||||
if err := json.Unmarshal(smallUpdateBytes, &u); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkWebhook_telebot(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
for b.Loop() {
|
||||
var u tele.Update
|
||||
if err := json.Unmarshal(smallUpdateBytes, &u); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkWebhook_gobot(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
for b.Loop() {
|
||||
var u gobotmodels.Update
|
||||
if err := json.Unmarshal(smallUpdateBytes, &u); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkWebhook_telego(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
for b.Loop() {
|
||||
var u telego.Update
|
||||
if err := json.Unmarshal(smallUpdateBytes, &u); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkWebhook_echotron(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
for b.Loop() {
|
||||
var u echotron.Update
|
||||
if err := json.Unmarshal(smallUpdateBytes, &u); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
+33
-15
@@ -6,6 +6,7 @@
|
||||
package transport
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/subtle"
|
||||
"errors"
|
||||
@@ -18,6 +19,24 @@ import (
|
||||
"github.com/lukaszraczylo/go-telegram/client"
|
||||
)
|
||||
|
||||
// webhookBufPool reuses *bytes.Buffer for incoming webhook bodies.
|
||||
// Webhook payloads are typically a single Telegram Update (commonly
|
||||
// 1-8 KiB), so a buffer that has grown once will satisfy most
|
||||
// subsequent requests with no additional allocation.
|
||||
var webhookBufPool = sync.Pool{New: func() any { return new(bytes.Buffer) }}
|
||||
|
||||
// maxWebhookBufCap caps the buffer size returned to webhookBufPool so
|
||||
// a rare oversized update doesn't permanently bloat the pool. Buffers
|
||||
// larger than this are dropped on the floor.
|
||||
const maxWebhookBufCap = 256 * 1024
|
||||
|
||||
func putWebhookBuf(buf *bytes.Buffer) {
|
||||
if buf.Cap() > maxWebhookBufCap {
|
||||
return
|
||||
}
|
||||
webhookBufPool.Put(buf)
|
||||
}
|
||||
|
||||
// WebhookServer implements Updater by exposing an http.Handler that
|
||||
// receives updates from Telegram. It can be mounted on the user's own
|
||||
// HTTP server (via ServeHTTP) or run standalone (via ListenAndServe).
|
||||
@@ -108,28 +127,27 @@ func (w *WebhookServer) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
w.handlers.Add(1)
|
||||
defer w.handlers.Done()
|
||||
|
||||
const maxBody = 1 << 20 // 1 MiB cap on body
|
||||
r.Body = http.MaxBytesReader(rw, r.Body, maxBody)
|
||||
defer func() { _ = r.Body.Close() }()
|
||||
|
||||
const max = 1 << 20 // 1 MiB cap on body
|
||||
buf := make([]byte, 0, 1024)
|
||||
tmp := make([]byte, 4096)
|
||||
for {
|
||||
n, err := r.Body.Read(tmp)
|
||||
if n > 0 {
|
||||
buf = append(buf, tmp[:n]...)
|
||||
if len(buf) > max {
|
||||
rw.WriteHeader(http.StatusRequestEntityTooLarge)
|
||||
return
|
||||
}
|
||||
}
|
||||
if errors.Is(err, http.ErrBodyReadAfterClose) || err != nil {
|
||||
break
|
||||
buf := webhookBufPool.Get().(*bytes.Buffer)
|
||||
buf.Reset()
|
||||
defer putWebhookBuf(buf)
|
||||
if _, err := buf.ReadFrom(r.Body); err != nil {
|
||||
var maxErr *http.MaxBytesError
|
||||
if errors.As(err, &maxErr) {
|
||||
rw.WriteHeader(http.StatusRequestEntityTooLarge)
|
||||
return
|
||||
}
|
||||
rw.WriteHeader(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
var u api.Update
|
||||
codec := w.Bot.Codec()
|
||||
if err := codec.Unmarshal(buf, &u); err != nil {
|
||||
if err := codec.Unmarshal(buf.Bytes(), &u); err != nil {
|
||||
rw.WriteHeader(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
package transport
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/lukaszraczylo/go-telegram/client"
|
||||
)
|
||||
|
||||
const benchUpdateBody = `{"update_id":12345,"message":{"message_id":1,"date":1700000000,"chat":{"id":42,"type":"private"},"from":{"id":42,"is_bot":false,"first_name":"User"},"text":"hello world"}}`
|
||||
|
||||
func BenchmarkWebhook_ServeHTTP(b *testing.B) {
|
||||
w := NewWebhookServer(client.New("t"), WithBufferSize(1024))
|
||||
body := []byte(benchUpdateBody)
|
||||
|
||||
done := make(chan struct{})
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case <-w.Updates():
|
||||
case <-done:
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
defer close(done)
|
||||
|
||||
b.ReportAllocs()
|
||||
for b.Loop() {
|
||||
req := httptest.NewRequest(http.MethodPost, "/", bytes.NewReader(body))
|
||||
rec := httptest.NewRecorder()
|
||||
w.ServeHTTP(rec, req)
|
||||
if rec.Code != http.StatusOK {
|
||||
b.Fatalf("status %d", rec.Code)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user