Compare commits

..

No commits in common. "master" and "v1.1.5" have entirely different histories.

19 changed files with 4568 additions and 67421 deletions

View file

@ -19,9 +19,9 @@ type Client struct {
listenerStore *listenerStore listenerStore *listenerStore
catchersStore *sync.Map catchersStore *sync.Map
successMsgStore *sync.Map successMsgStore *sync.Map
forwardMsgStore *sync.Map
updatesTimeout time.Duration updatesTimeout time.Duration
catchTimeout time.Duration catchTimeout time.Duration
DisablePatch bool
} }
type Option func(*Client) type Option func(*Client)
@ -44,12 +44,6 @@ func WithProxy(req *AddProxyRequest) Option {
} }
} }
func WithoutSendMessagePatch() Option {
return func(client *Client) {
client.DisablePatch = true
}
}
func SetLogLevel(level int32) { func SetLogLevel(level int32) {
_, _ = SetLogVerbosityLevel(&SetLogVerbosityLevelRequest{ _, _ = SetLogVerbosityLevel(&SetLogVerbosityLevelRequest{
NewVerbosityLevel: level, NewVerbosityLevel: level,
@ -81,20 +75,21 @@ func NewClient(authorizationStateHandler AuthorizationStateHandler, options ...O
listenerStore: newListenerStore(), listenerStore: newListenerStore(),
catchersStore: &sync.Map{}, catchersStore: &sync.Map{},
successMsgStore: &sync.Map{}, successMsgStore: &sync.Map{},
forwardMsgStore: &sync.Map{},
} }
client.extraGenerator = UuidV4Generator() client.extraGenerator = UuidV4Generator()
client.catchTimeout = 60 * time.Second client.catchTimeout = 60 * time.Second
for _, option := range options {
option(client)
}
tdlibInstance.addClient(client) tdlibInstance.addClient(client)
go client.processPendingResponse() go client.processPendingResponse()
go client.receiver() go client.receiver()
for _, option := range options {
go option(client)
}
err := Authorize(client, authorizationStateHandler) err := Authorize(client, authorizationStateHandler)
if err != nil { if err != nil {
return nil, err return nil, err
@ -116,11 +111,15 @@ func (client *Client) processResponse(response *Response) {
return return
} }
if !client.DisablePatch && typ.GetType() == (&UpdateMessageSendSucceeded{}).GetType() { if typ.GetType() == (&UpdateMessageSendSucceeded{}).GetType() {
sendVal, sOk := client.successMsgStore.Load(typ.(*UpdateMessageSendSucceeded).OldMessageId) sendVal, sOk := client.successMsgStore.Load(typ.(*UpdateMessageSendSucceeded).OldMessageId)
if sOk { if sOk {
sendVal.(chan *Response) <- response sendVal.(chan *Response) <- response
} }
forwardVal, fOk := client.forwardMsgStore.Load(typ.(*UpdateMessageSendSucceeded).OldMessageId)
if fOk {
forwardVal.(chan *Response) <- response
}
} }
if len(client.listenerStore.Listeners()) == 0 { if len(client.listenerStore.Listeners()) == 0 {
@ -134,18 +133,7 @@ func (client *Client) processResponse(response *Response) {
needGc := false needGc := false
for _, listener := range client.listenerStore.Listeners() { for _, listener := range client.listenerStore.Listeners() {
if listener.IsActive() && listener.Updates != nil && typ.GetType() == listener.Filter.GetType() { // All updates go to Updates channel if type == filter if listener.IsActive() && listener.Updates != nil && typ.GetType() == listener.Filter.GetType() { // All updates go to Updates channel if type == filter
// Make some delay to UpdateMessageSendSucceeded listener
// This can make UpdateMessageSendSucceeded response later than sendMessage response.
// This may help a bot developer to map temporary message id to actual message id easily.
// Cause an event listener slower than sendMessage response, so you have enough time to do mapping stuff.
if typ.GetType() == (&UpdateMessageSendSucceeded{}).GetType() {
go func(listener *Listener, typ Type) {
time.Sleep(5 * time.Millisecond)
listener.Updates <- typ listener.Updates <- typ
}(listener, typ)
} else {
listener.Updates <- typ
}
} else if listener.IsActive() && listener.RawUpdates != nil { // All updates go to RawUpdates channel if filter is empty } else if listener.IsActive() && listener.RawUpdates != nil { // All updates go to RawUpdates channel if filter is empty
listener.RawUpdates <- typ listener.RawUpdates <- typ
} else if !listener.IsActive() { // GC inactive listener } else if !listener.IsActive() { // GC inactive listener
@ -155,10 +143,6 @@ func (client *Client) processResponse(response *Response) {
if needGc { if needGc {
client.listenerStore.gc() client.listenerStore.gc()
} }
if typ.GetType() == TypeUpdateAuthorizationState && typ.(*UpdateAuthorizationState).AuthorizationState.AuthorizationStateType() == TypeAuthorizationStateClosed {
close(client.responses)
}
} }
func (client *Client) receiver() { func (client *Client) receiver() {
@ -206,7 +190,7 @@ func (client *Client) Send(req Request) (*Response, error) {
select { select {
case response := <-catcher: case response := <-catcher:
if !client.DisablePatch && response.Type != "error" && req.Type == "sendMessage" { if response.Type != "error" && req.Type == "sendMessage" {
m, err := UnmarshalMessage(response.Data) m, err := UnmarshalMessage(response.Data)
if err != nil { if err != nil {
return nil, err return nil, err
@ -227,7 +211,7 @@ func (client *Client) Send(req Request) (*Response, error) {
if err2 != nil { if err2 != nil {
return response, nil return response, nil
} }
response.Data = bytes.Replace(response.Data, []byte("\"@type\":\"messageSendingStatePending\""), []byte("\"@type\":\"updateMessageSendSucceeded\""), 1) response.Data = bytes.Replace(response.Data, []byte("{\"@type\":\"messageSendingStatePending\"}"), []byte("{\"@type\":\"updateMessageSendSucceeded\"}"), 1)
response.Data = bytes.Replace(response.Data, []byte("\"id\":"+strconv.FormatInt(m.Id, 10)), []byte("\"id\":"+strconv.FormatInt(m2.Message.Id, 10)), 1) response.Data = bytes.Replace(response.Data, []byte("\"id\":"+strconv.FormatInt(m.Id, 10)), []byte("\"id\":"+strconv.FormatInt(m2.Message.Id, 10)), 1)
return response, nil return response, nil
case <-time.After(1 * time.Second): case <-time.After(1 * time.Second):
@ -261,3 +245,7 @@ func (client *Client) AddEventReceiver(msgType Type, channelCapacity int) *Liste
return listener return listener
} }
func (client *Client) Stop() {
client.Destroy()
}

View file

@ -1,49 +1,67 @@
package client package client
import ( import (
"fmt"
"math/rand"
"strings" "strings"
"github.com/google/uuid"
) )
type ExtraGenerator func() string type ExtraGenerator func() string
func UuidV4Generator() ExtraGenerator { func UuidV4Generator() ExtraGenerator {
return func() string { return func() string {
return uuid.NewString() var uuid [16]byte
rand.Read(uuid[:])
uuid[6] = (uuid[6] & 0x0f) | 0x40
uuid[8] = (uuid[8] & 0x3f) | 0x80
return fmt.Sprintf("%08x-%04x-%04x-%04x-%012x", uuid[:4], uuid[4:6], uuid[6:8], uuid[8:10], uuid[10:])
} }
} }
func IsCommand(text string) bool { func IsCommmand(text string) bool {
if i := strings.Index(text, "/"); i == 0 { if text != "" {
if text[0] == '/' {
return true return true
} }
}
return false return false
} }
func CheckCommand(text string, entities []*TextEntity) string { func CheckCommand(text string, entities []*TextEntity) string {
if IsCommand(text) { if IsCommmand(text) {
cmd := text // Check text entities and make bot happy!
if len(entities) >= 1 {
// e.g. ["/hello 123", "/hell o 123"] // Get first command
// Result: "/hello", "/hell" if entities[0].Type.TextEntityTypeType() == "textEntityTypeBotCommand" {
if i := strings.Index(cmd, " "); i != -1 { // e.g.: { "text": "/hello@world_bot", "textEntity": { offset: 0, length: 16 } }
cmd = cmd[:i] // Result: "/hello"
if i := strings.Index(text[:entities[0].Length], "@"); i != -1 {
return text[:i]
} }
return text[:entities[0].Length]
}
} else {
// Since userbot does not have bot command entities in Private Chat, so make userbot happy too!
// e.g.: ["/hello@world_bot", "/hello@", "/hello@123"] // e.g.: ["/hello@world_bot", "/hello@", "/hello@123"]
// Result: "/hello" // Result: "/hello"
if i := strings.Index(cmd, "@"); i != -1 { if i := strings.Index(text, "@"); i != -1 {
cmd = cmd[:i] return text[:i]
}
// e.g. ["/hello 123", "/hell o 123"]
// Result: "/hello", "/hell"
if i := strings.Index(text, " "); i != -1 {
return text[:i]
}
return text
} }
return cmd
} }
return "" return ""
} }
func CommandArgument(text string) string { func CommandArgument(text string) string {
if IsCommand(text) { if IsCommmand(text) {
// e.g. ["/hello 123", "/hell o 123"] // e.g. ["/hello 123", "/hell o 123"]
// Result: "123", "o 123" // Result: "123", "o 123"
if i := strings.Index(text, " "); i != -1 { if i := strings.Index(text, " "); i != -1 {

File diff suppressed because it is too large Load diff

View file

@ -1,12 +1,10 @@
package client package client
//#cgo linux CFLAGS: -I/usr/local/include //#cgo linux CFLAGS: -I/usr/local/include
//#cgo freebsd CFLAGS: -I/usr/local/include
//#cgo darwin CFLAGS: -I/usr/local/include //#cgo darwin CFLAGS: -I/usr/local/include
//#cgo windows CFLAGS: -IE:/src/tdlib -IE:/src/tdlib/build //#cgo windows CFLAGS: -IE:/src/tdlib -IE:/src/tdlib/build
//#cgo linux LDFLAGS: -L/usr/local/lib -ltdjson_static -ltdjson_private -ltdclient -ltdcore -ltdapi -ltdactor -ltddb -ltde2e -ltdsqlite -ltdmtproto -ltdnet -ltdutils -lstdc++ -lssl -lcrypto -ldl -lz -lm //#cgo linux LDFLAGS: -L/usr/local/lib -ltdjson_static -ltdjson_private -ltdclient -ltdcore -ltdapi -ltdactor -ltddb -ltdsqlite -ltdnet -ltdutils -lstdc++ -lssl -lcrypto -ldl -lz -lm
//#cgo freebsd LDFLAGS: -L/usr/local/lib -ltdjson_static -ltdjson_private -ltdclient -ltdcore -ltdapi -ltdactor -ltddb -ltde2e -ltdsqlite -ltdmtproto -ltdnet -ltdutils -lstdc++ -lssl -lcrypto -ldl -lz -lm //#cgo darwin LDFLAGS: -L/usr/local/lib -L/usr/local/opt/openssl/lib -ltdjson_static -ltdjson_private -ltdclient -ltdcore -ltdapi -ltdactor -ltddb -ltdsqlite -ltdnet -ltdutils -lstdc++ -lssl -lcrypto -ldl -lz -lm
//#cgo darwin LDFLAGS: -L/usr/local/lib -L/usr/local/opt/openssl/lib -ltdjson_static -ltdjson_private -ltdclient -ltdcore -ltdapi -ltdactor -ltddb -ltde2e -ltdsqlite -ltdmtproto -ltdnet -ltdutils -lstdc++ -lssl -lcrypto -ldl -lz -lm
//#cgo windows LDFLAGS: -LE:/src/tdlib/build/Release -ltdjson //#cgo windows LDFLAGS: -LE:/src/tdlib/build/Release -ltdjson
//#include <stdlib.h> //#include <stdlib.h>
//#include <td/telegram/td_json_client.h> //#include <td/telegram/td_json_client.h>

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -24,6 +24,8 @@ func GetTdParameters() *tdlib.SetTdlibParametersRequest {
DeviceModel: "HuskyNG", DeviceModel: "HuskyNG",
SystemVersion: "3.0", SystemVersion: "3.0",
ApplicationVersion: "3.0", ApplicationVersion: "3.0",
EnableStorageOptimizer: true,
IgnoreFileNames: false,
} }
} }
@ -58,7 +60,7 @@ func main() {
log.Fatalf("GetMe error: %s", err) log.Fatalf("GetMe error: %s", err)
} }
log.Printf("%v connected", me.Usernames) log.Printf("%s connected", me.Username)
listener := client.AddEventReceiver(&tdlib.UpdateNewMessage{}, 1000) listener := client.AddEventReceiver(&tdlib.UpdateNewMessage{}, 1000)
@ -85,9 +87,7 @@ func main() {
}) })
m, err := client.SendMessage(&tdlib.SendMessageRequest{ m, err := client.SendMessage(&tdlib.SendMessageRequest{
ChatId: chatId, ChatId: chatId,
ReplyTo: &tdlib.InputMessageReplyToMessage{ ReplyToMessageId: msgId,
MessageId: msgId,
},
InputMessageContent: &tdlib.InputMessageText{ InputMessageContent: &tdlib.InputMessageText{
Text: text, Text: text,
}, },

View file

@ -32,6 +32,8 @@ func GetTdParameters() *tdlib.SetTdlibParametersRequest {
DeviceModel: "HuskyNG", DeviceModel: "HuskyNG",
SystemVersion: "3.0", SystemVersion: "3.0",
ApplicationVersion: "3.0", ApplicationVersion: "3.0",
EnableStorageOptimizer: true,
IgnoreFileNames: false,
} }
} }
@ -66,7 +68,7 @@ func main() {
log.Fatalf("GetMe error: %s", err) log.Fatalf("GetMe error: %s", err)
} }
log.Printf("%v connected", me.Usernames) log.Printf("%s connected", me.Username)
listener := client.AddEventReceiver(&tdlib.UpdateNewMessage{}, 1000) listener := client.AddEventReceiver(&tdlib.UpdateNewMessage{}, 1000)
@ -96,9 +98,7 @@ func main() {
}) })
m, err := client.SendMessage(&tdlib.SendMessageRequest{ m, err := client.SendMessage(&tdlib.SendMessageRequest{
ChatId: chatId, ChatId: chatId,
ReplyTo: &tdlib.InputMessageReplyToMessage{ ReplyToMessageId: msgId,
MessageId: msgId,
},
InputMessageContent: &tdlib.InputMessageText{ InputMessageContent: &tdlib.InputMessageText{
Text: text, Text: text,
}, },
@ -110,9 +110,7 @@ func main() {
case "/repeat": case "/repeat":
m, err := client.SendMessage(&tdlib.SendMessageRequest{ m, err := client.SendMessage(&tdlib.SendMessageRequest{
ChatId: chatId, ChatId: chatId,
ReplyTo: &tdlib.InputMessageReplyToMessage{ ReplyToMessageId: msgId,
MessageId: msgId,
},
InputMessageContent: &tdlib.InputMessageText{ InputMessageContent: &tdlib.InputMessageText{
Text: &tdlib.FormattedText{Text: tdlib.CommandArgument(msgText)}, Text: &tdlib.FormattedText{Text: tdlib.CommandArgument(msgText)},
}, },

View file

@ -32,6 +32,8 @@ func GetTdParameters() *tdlib.SetTdlibParametersRequest {
DeviceModel: "HuskyNG", DeviceModel: "HuskyNG",
SystemVersion: "3.0", SystemVersion: "3.0",
ApplicationVersion: "3.0", ApplicationVersion: "3.0",
EnableStorageOptimizer: true,
IgnoreFileNames: false,
} }
} }
@ -66,7 +68,7 @@ func main() {
log.Fatalf("GetMe error: %s", err) log.Fatalf("GetMe error: %s", err)
} }
log.Printf("%v connected", me.Usernames) log.Printf("%s connected", me.Username)
listener := client.AddEventReceiver(&tdlib.UpdateNewMessage{}, 1000) listener := client.AddEventReceiver(&tdlib.UpdateNewMessage{}, 1000)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 794 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 900 KiB

View file

@ -32,6 +32,8 @@ func GetTdParameters() *tdlib.SetTdlibParametersRequest {
DeviceModel: "HuskyNG", DeviceModel: "HuskyNG",
SystemVersion: "3.0", SystemVersion: "3.0",
ApplicationVersion: "3.0", ApplicationVersion: "3.0",
EnableStorageOptimizer: true,
IgnoreFileNames: false,
} }
} }
@ -66,7 +68,7 @@ func main() {
log.Fatalf("GetMe error: %s", err) log.Fatalf("GetMe error: %s", err)
} }
log.Printf("%v connected", me.Usernames) log.Printf("%s connected", me.Username)
listener := client.AddEventReceiver(&tdlib.UpdateNewMessage{}, 1000) listener := client.AddEventReceiver(&tdlib.UpdateNewMessage{}, 1000)
@ -96,12 +98,10 @@ func main() {
}) })
m, err := client.SendMessage(&tdlib.SendMessageRequest{ m, err := client.SendMessage(&tdlib.SendMessageRequest{
ChatId: chatId, ChatId: chatId,
ReplyTo: &tdlib.InputMessageReplyToMessage{ ReplyToMessageId: msgId,
MessageId: msgId,
},
InputMessageContent: &tdlib.InputMessagePhoto{ InputMessageContent: &tdlib.InputMessagePhoto{
Photo: &tdlib.InputFileLocal{ Photo: &tdlib.InputFileLocal{
Path: "./Meru_01.png", Path: "./myht9-1486821485193084928.jpg",
}, },
Caption: text, Caption: text,
}, },
@ -117,19 +117,17 @@ func main() {
}) })
m, err := client.SendMessageAlbum(&tdlib.SendMessageAlbumRequest{ m, err := client.SendMessageAlbum(&tdlib.SendMessageAlbumRequest{
ChatId: chatId, ChatId: chatId,
ReplyTo: &tdlib.InputMessageReplyToMessage{ ReplyToMessageId: msgId,
MessageId: msgId,
},
InputMessageContents: []tdlib.InputMessageContent{ InputMessageContents: []tdlib.InputMessageContent{
&tdlib.InputMessagePhoto{ &tdlib.InputMessagePhoto{
Photo: &tdlib.InputFileLocal{ Photo: &tdlib.InputFileLocal{
Path: "./Meru_01.png", Path: "./myht9-1486821485193084928.jpg",
}, },
Caption: text, Caption: text,
}, },
&tdlib.InputMessagePhoto{ &tdlib.InputMessagePhoto{
Photo: &tdlib.InputFileLocal{ Photo: &tdlib.InputFileLocal{
Path: "./Meru_02.png", Path: "./hisagi_02-1486983199280738309.jpg",
}, },
}, },
}, },

Binary file not shown.

After

Width:  |  Height:  |  Size: 153 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

View file

@ -24,6 +24,8 @@ func GetTdParameters() *tdlib.SetTdlibParametersRequest {
DeviceModel: "HuskyNG", DeviceModel: "HuskyNG",
SystemVersion: "3.0", SystemVersion: "3.0",
ApplicationVersion: "3.0", ApplicationVersion: "3.0",
EnableStorageOptimizer: true,
IgnoreFileNames: false,
} }
} }
@ -63,7 +65,7 @@ func main() {
log.Fatalf("GetMe error: %s", err) log.Fatalf("GetMe error: %s", err)
} }
log.Printf("%v connected", me.Usernames) log.Printf("%s connected", me.Username)
listener := client.AddEventReceiver(&tdlib.UpdateNewMessage{}, 1000) listener := client.AddEventReceiver(&tdlib.UpdateNewMessage{}, 1000)
@ -90,9 +92,7 @@ func main() {
}) })
m, err := client.SendMessage(&tdlib.SendMessageRequest{ m, err := client.SendMessage(&tdlib.SendMessageRequest{
ChatId: chatId, ChatId: chatId,
ReplyTo: &tdlib.InputMessageReplyToMessage{ ReplyToMessageId: msgId,
MessageId: msgId,
},
InputMessageContent: &tdlib.InputMessageText{ InputMessageContent: &tdlib.InputMessageText{
Text: text, Text: text,
}, },

View file

@ -32,6 +32,8 @@ func GetTdParameters() *tdlib.SetTdlibParametersRequest {
DeviceModel: "HuskyNG", DeviceModel: "HuskyNG",
SystemVersion: "3.0", SystemVersion: "3.0",
ApplicationVersion: "3.0", ApplicationVersion: "3.0",
EnableStorageOptimizer: true,
IgnoreFileNames: false,
} }
} }
@ -66,7 +68,7 @@ func main() {
log.Fatalf("GetMe error: %s", err) log.Fatalf("GetMe error: %s", err)
} }
log.Printf("%v connected", me.Usernames) log.Printf("%s connected", me.Username)
listener := client.GetListener() listener := client.GetListener()

5
go.mod
View file

@ -2,7 +2,4 @@ module github.com/c0re100/gotdlib
go 1.16 go 1.16
require ( require golang.org/x/crypto v0.0.0-20220128200615-198e4374d7ed
github.com/google/uuid v1.6.0
golang.org/x/crypto v0.31.0
)

72
go.sum
View file

@ -1,69 +1,11 @@
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= golang.org/x/crypto v0.0.0-20220128200615-198e4374d7ed h1:YoWVYYAfvQ4ddHv3OKmIvX7NCAhFGTj62VP2l2kfBbA=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= golang.org/x/crypto v0.0.0-20220128200615-198e4374d7ed/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 h1:SrN+KX8Art/Sf4HNj6Zcz06G7VEz+7w9tdXTPOZ7+l4=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/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-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 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.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q=
golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=