summaryrefslogtreecommitdiffstats
path: root/vendor/github.com
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com')
-rw-r--r--vendor/github.com/bwmarrin/discordgo/components.go46
-rw-r--r--vendor/github.com/bwmarrin/discordgo/discord.go2
-rw-r--r--vendor/github.com/bwmarrin/discordgo/endpoints.go17
-rw-r--r--vendor/github.com/bwmarrin/discordgo/events.go15
-rw-r--r--vendor/github.com/bwmarrin/discordgo/interactions.go16
-rw-r--r--vendor/github.com/bwmarrin/discordgo/message.go8
-rw-r--r--vendor/github.com/bwmarrin/discordgo/restapi.go1067
-rw-r--r--vendor/github.com/bwmarrin/discordgo/state.go33
-rw-r--r--vendor/github.com/bwmarrin/discordgo/structs.go299
-rw-r--r--vendor/github.com/bwmarrin/discordgo/util.go18
-rw-r--r--vendor/github.com/bwmarrin/discordgo/voice.go21
-rw-r--r--vendor/github.com/bwmarrin/discordgo/wsapi.go10
-rw-r--r--vendor/github.com/hashicorp/golang-lru/.golangci.yml30
-rw-r--r--vendor/github.com/hashicorp/golang-lru/2q.go3
-rw-r--r--vendor/github.com/hashicorp/golang-lru/LICENSE2
-rw-r--r--vendor/github.com/hashicorp/golang-lru/README.md2
-rw-r--r--vendor/github.com/hashicorp/golang-lru/arc.go1
-rw-r--r--vendor/github.com/hashicorp/golang-lru/lru.go119
-rw-r--r--vendor/github.com/hashicorp/golang-lru/simplelru/lru.go6
-rw-r--r--vendor/github.com/hashicorp/golang-lru/simplelru/lru_interface.go5
-rw-r--r--vendor/github.com/hashicorp/golang-lru/testing.go16
-rw-r--r--vendor/github.com/keybase/go-keybase-chat-bot/kbchat/chat.go12
-rw-r--r--vendor/github.com/keybase/go-keybase-chat-bot/kbchat/kbchat.go140
-rw-r--r--vendor/github.com/kyokomi/emoji/v2/README.md2
-rw-r--r--vendor/github.com/kyokomi/emoji/v2/emoji_codemap.go55
-rw-r--r--vendor/github.com/kyokomi/emoji/v2/wercker.yml33
-rw-r--r--vendor/github.com/labstack/echo/v4/CHANGELOG.md37
-rw-r--r--vendor/github.com/labstack/echo/v4/Makefile6
-rw-r--r--vendor/github.com/labstack/echo/v4/context.go13
-rw-r--r--vendor/github.com/labstack/echo/v4/echo.go146
-rw-r--r--vendor/github.com/labstack/echo/v4/echo_fs.go18
-rw-r--r--vendor/github.com/labstack/echo/v4/ip.go7
-rw-r--r--vendor/github.com/labstack/echo/v4/middleware/body_dump.go5
-rw-r--r--vendor/github.com/labstack/echo/v4/middleware/compress.go5
-rw-r--r--vendor/github.com/labstack/echo/v4/middleware/csrf.go2
-rw-r--r--vendor/github.com/labstack/echo/v4/middleware/extractor.go20
-rw-r--r--vendor/github.com/labstack/echo/v4/middleware/jwt.go6
-rw-r--r--vendor/github.com/labstack/echo/v4/middleware/logger.go14
-rw-r--r--vendor/github.com/labstack/echo/v4/middleware/proxy.go17
-rw-r--r--vendor/github.com/labstack/echo/v4/middleware/rate_limiter.go11
-rw-r--r--vendor/github.com/labstack/echo/v4/middleware/request_logger.go102
-rw-r--r--vendor/github.com/labstack/echo/v4/middleware/slash.go2
-rw-r--r--vendor/github.com/labstack/echo/v4/router.go46
-rw-r--r--vendor/github.com/lrstanley/girc/.editorconfig4
-rw-r--r--vendor/github.com/lrstanley/girc/README.md2
-rw-r--r--vendor/github.com/magiconair/properties/.travis.yml17
-rw-r--r--vendor/github.com/magiconair/properties/CHANGELOG.md45
-rw-r--r--vendor/github.com/magiconair/properties/decode.go66
-rw-r--r--vendor/github.com/magiconair/properties/doc.go127
-rw-r--r--vendor/github.com/magiconair/properties/integrate.go7
-rw-r--r--vendor/github.com/magiconair/properties/lex.go2
-rw-r--r--vendor/github.com/magiconair/properties/load.go2
-rw-r--r--vendor/github.com/magiconair/properties/parser.go2
-rw-r--r--vendor/github.com/magiconair/properties/properties.go17
-rw-r--r--vendor/github.com/magiconair/properties/rangecheck.go2
-rw-r--r--vendor/github.com/pelletier/go-toml/v2/.goreleaser.yaml12
-rw-r--r--vendor/github.com/pelletier/go-toml/v2/README.md11
-rw-r--r--vendor/github.com/pelletier/go-toml/v2/decode.go88
-rw-r--r--vendor/github.com/pelletier/go-toml/v2/errors.go33
-rw-r--r--vendor/github.com/pelletier/go-toml/v2/internal/ast/builder.go51
-rw-r--r--vendor/github.com/pelletier/go-toml/v2/internal/characters/ascii.go42
-rw-r--r--vendor/github.com/pelletier/go-toml/v2/internal/characters/utf8.go (renamed from vendor/github.com/pelletier/go-toml/v2/utf8.go)53
-rw-r--r--vendor/github.com/pelletier/go-toml/v2/internal/tracker/key.go12
-rw-r--r--vendor/github.com/pelletier/go-toml/v2/internal/tracker/seen.go28
-rw-r--r--vendor/github.com/pelletier/go-toml/v2/localtime.go6
-rw-r--r--vendor/github.com/pelletier/go-toml/v2/marshaler.go108
-rw-r--r--vendor/github.com/pelletier/go-toml/v2/strict.go34
-rw-r--r--vendor/github.com/pelletier/go-toml/v2/types.go10
-rw-r--r--vendor/github.com/pelletier/go-toml/v2/unmarshaler.go180
-rw-r--r--vendor/github.com/pelletier/go-toml/v2/unstable/ast.go (renamed from vendor/github.com/pelletier/go-toml/v2/internal/ast/ast.go)74
-rw-r--r--vendor/github.com/pelletier/go-toml/v2/unstable/builder.go71
-rw-r--r--vendor/github.com/pelletier/go-toml/v2/unstable/doc.go3
-rw-r--r--vendor/github.com/pelletier/go-toml/v2/unstable/kind.go (renamed from vendor/github.com/pelletier/go-toml/v2/internal/ast/kind.go)12
-rw-r--r--vendor/github.com/pelletier/go-toml/v2/unstable/parser.go (renamed from vendor/github.com/pelletier/go-toml/v2/parser.go)293
-rw-r--r--vendor/github.com/pelletier/go-toml/v2/unstable/scanner.go (renamed from vendor/github.com/pelletier/go-toml/v2/scanner.go)50
-rw-r--r--vendor/github.com/saintfish/chardet/README.md2
-rw-r--r--vendor/github.com/slack-go/slack/auth.go34
-rw-r--r--vendor/github.com/slack-go/slack/block_conv.go12
-rw-r--r--vendor/github.com/slack-go/slack/block_element.go92
-rw-r--r--vendor/github.com/slack-go/slack/block_rich_text.go6
-rw-r--r--vendor/github.com/slack-go/slack/conversation.go73
-rw-r--r--vendor/github.com/slack-go/slack/files.go179
-rw-r--r--vendor/github.com/slack-go/slack/misc.go3
-rw-r--r--vendor/github.com/slack-go/slack/team.go69
-rw-r--r--vendor/github.com/slack-go/slack/users.go105
-rw-r--r--vendor/github.com/slack-go/slack/webhooks.go4
-rw-r--r--vendor/github.com/slack-go/slack/websocket_reactions.go12
-rw-r--r--vendor/github.com/slack-go/slack/workflow_step_execute.go6
-rw-r--r--vendor/github.com/spf13/afero/.travis.yml26
-rw-r--r--vendor/github.com/spf13/afero/README.md2
-rw-r--r--vendor/github.com/spf13/afero/afero.go4
-rw-r--r--vendor/github.com/spf13/afero/appveyor.yml9
-rw-r--r--vendor/github.com/spf13/afero/basepath.go14
-rw-r--r--vendor/github.com/spf13/afero/const_bsds.go1
-rw-r--r--vendor/github.com/spf13/afero/const_win_unix.go8
-rw-r--r--vendor/github.com/spf13/afero/httpFs.go2
-rw-r--r--vendor/github.com/spf13/afero/internal/common/adapters.go27
-rw-r--r--vendor/github.com/spf13/afero/iofs.go38
-rw-r--r--vendor/github.com/spf13/afero/ioutil.go10
-rw-r--r--vendor/github.com/spf13/afero/mem/file.go30
-rw-r--r--vendor/github.com/spf13/afero/memmap.go5
-rw-r--r--vendor/github.com/spf13/afero/unionFile.go2
-rw-r--r--vendor/github.com/spf13/afero/util.go10
-rw-r--r--vendor/github.com/spf13/viper/Makefile4
-rw-r--r--vendor/github.com/spf13/viper/README.md21
-rw-r--r--vendor/github.com/spf13/viper/internal/encoding/toml/codec.go29
-rw-r--r--vendor/github.com/spf13/viper/internal/encoding/toml/codec2.go19
-rw-r--r--vendor/github.com/spf13/viper/internal/encoding/yaml/codec.go2
-rw-r--r--vendor/github.com/spf13/viper/internal/encoding/yaml/yaml2.go14
-rw-r--r--vendor/github.com/spf13/viper/internal/encoding/yaml/yaml3.go14
-rw-r--r--vendor/github.com/spf13/viper/logger.go4
-rw-r--r--vendor/github.com/spf13/viper/util.go33
-rw-r--r--vendor/github.com/spf13/viper/viper.go120
-rw-r--r--vendor/github.com/spf13/viper/watch.go4
-rw-r--r--vendor/github.com/spf13/viper/watch_unsupported.go (renamed from vendor/github.com/spf13/viper/watch_wasm.go)14
-rw-r--r--vendor/github.com/subosito/gotenv/.gitignore1
-rw-r--r--vendor/github.com/subosito/gotenv/.golangci.yaml7
-rw-r--r--vendor/github.com/subosito/gotenv/CHANGELOG.md12
-rw-r--r--vendor/github.com/subosito/gotenv/README.md3
-rw-r--r--vendor/github.com/subosito/gotenv/gotenv.go189
-rw-r--r--vendor/github.com/valyala/fasttemplate/template.go3
121 files changed, 3427 insertions, 1750 deletions
diff --git a/vendor/github.com/bwmarrin/discordgo/components.go b/vendor/github.com/bwmarrin/discordgo/components.go
index 6ee4e289..a5f86b34 100644
--- a/vendor/github.com/bwmarrin/discordgo/components.go
+++ b/vendor/github.com/bwmarrin/discordgo/components.go
@@ -10,10 +10,14 @@ type ComponentType uint
// MessageComponent types.
const (
- ActionsRowComponent ComponentType = 1
- ButtonComponent ComponentType = 2
- SelectMenuComponent ComponentType = 3
- TextInputComponent ComponentType = 4
+ ActionsRowComponent ComponentType = 1
+ ButtonComponent ComponentType = 2
+ SelectMenuComponent ComponentType = 3
+ TextInputComponent ComponentType = 4
+ UserSelectMenuComponent ComponentType = 5
+ RoleSelectMenuComponent ComponentType = 6
+ MentionableSelectMenuComponent ComponentType = 7
+ ChannelSelectMenuComponent ComponentType = 8
)
// MessageComponent is a base interface for all message components.
@@ -41,7 +45,8 @@ func (umc *unmarshalableMessageComponent) UnmarshalJSON(src []byte) error {
umc.MessageComponent = &ActionsRow{}
case ButtonComponent:
umc.MessageComponent = &Button{}
- case SelectMenuComponent:
+ case SelectMenuComponent, ChannelSelectMenuComponent, UserSelectMenuComponent,
+ RoleSelectMenuComponent, MentionableSelectMenuComponent:
umc.MessageComponent = &SelectMenu{}
case TextInputComponent:
umc.MessageComponent = &TextInput{}
@@ -169,8 +174,23 @@ type SelectMenuOption struct {
Default bool `json:"default"`
}
+// SelectMenuType represents select menu type.
+type SelectMenuType ComponentType
+
+// SelectMenu types.
+const (
+ StringSelectMenu = SelectMenuType(SelectMenuComponent)
+ UserSelectMenu = SelectMenuType(UserSelectMenuComponent)
+ RoleSelectMenu = SelectMenuType(RoleSelectMenuComponent)
+ MentionableSelectMenu = SelectMenuType(MentionableSelectMenuComponent)
+ ChannelSelectMenu = SelectMenuType(ChannelSelectMenuComponent)
+)
+
// SelectMenu represents select menu component.
type SelectMenu struct {
+ // Type of the select menu.
+ MenuType SelectMenuType `json:"type,omitempty"`
+ // CustomID is a developer-defined identifier for the select menu.
CustomID string `json:"custom_id,omitempty"`
// The text which will be shown in the menu if there's no default options or all options was deselected and component was closed.
Placeholder string `json:"placeholder"`
@@ -179,25 +199,31 @@ type SelectMenu struct {
// This value determines the maximal amount of selected items in the menu.
// If MaxValues or MinValues are greater than one then the user can select multiple items in the component.
MaxValues int `json:"max_values,omitempty"`
- Options []SelectMenuOption `json:"options"`
+ Options []SelectMenuOption `json:"options,omitempty"`
Disabled bool `json:"disabled"`
+
+ // NOTE: Can only be used in SelectMenu with Channel menu type.
+ ChannelTypes []ChannelType `json:"channel_types,omitempty"`
}
// Type is a method to get the type of a component.
-func (SelectMenu) Type() ComponentType {
+func (s SelectMenu) Type() ComponentType {
+ if s.MenuType != 0 {
+ return ComponentType(s.MenuType)
+ }
return SelectMenuComponent
}
// MarshalJSON is a method for marshaling SelectMenu to a JSON object.
-func (m SelectMenu) MarshalJSON() ([]byte, error) {
+func (s SelectMenu) MarshalJSON() ([]byte, error) {
type selectMenu SelectMenu
return Marshal(struct {
selectMenu
Type ComponentType `json:"type"`
}{
- selectMenu: selectMenu(m),
- Type: m.Type(),
+ selectMenu: selectMenu(s),
+ Type: s.Type(),
})
}
diff --git a/vendor/github.com/bwmarrin/discordgo/discord.go b/vendor/github.com/bwmarrin/discordgo/discord.go
index fc7b6d7a..0b571764 100644
--- a/vendor/github.com/bwmarrin/discordgo/discord.go
+++ b/vendor/github.com/bwmarrin/discordgo/discord.go
@@ -22,7 +22,7 @@ import (
)
// VERSION of DiscordGo, follows Semantic Versioning. (http://semver.org/)
-const VERSION = "0.26.1"
+const VERSION = "0.27.0"
// New creates a new Discord session with provided token.
// If the token is for a bot, it must be prefixed with "Bot "
diff --git a/vendor/github.com/bwmarrin/discordgo/endpoints.go b/vendor/github.com/bwmarrin/discordgo/endpoints.go
index 375b75b5..a2a05fe3 100644
--- a/vendor/github.com/bwmarrin/discordgo/endpoints.go
+++ b/vendor/github.com/bwmarrin/discordgo/endpoints.go
@@ -60,11 +60,12 @@ var (
return EndpointCDNBanners + uID + "/" + cID + ".gif"
}
- EndpointUserGuilds = func(uID string) string { return EndpointUsers + uID + "/guilds" }
- EndpointUserGuild = func(uID, gID string) string { return EndpointUsers + uID + "/guilds/" + gID }
- EndpointUserGuildMember = func(uID, gID string) string { return EndpointUserGuild(uID, gID) + "/member" }
- EndpointUserChannels = func(uID string) string { return EndpointUsers + uID + "/channels" }
- EndpointUserConnections = func(uID string) string { return EndpointUsers + uID + "/connections" }
+ EndpointUserGuilds = func(uID string) string { return EndpointUsers + uID + "/guilds" }
+ EndpointUserGuild = func(uID, gID string) string { return EndpointUsers + uID + "/guilds/" + gID }
+ EndpointUserGuildMember = func(uID, gID string) string { return EndpointUserGuild(uID, gID) + "/member" }
+ EndpointUserChannels = func(uID string) string { return EndpointUsers + uID + "/channels" }
+ EndpointUserApplicationRoleConnection = func(aID string) string { return EndpointUsers + "@me/applications/" + aID + "/role-connection" }
+ EndpointUserConnections = func(uID string) string { return EndpointUsers + uID + "/connections" }
EndpointGuild = func(gID string) string { return EndpointGuilds + gID }
EndpointGuildAutoModeration = func(gID string) string { return EndpointGuild(gID) + "/auto-moderation" }
@@ -96,6 +97,7 @@ var (
EndpointGuildEmojis = func(gID string) string { return EndpointGuilds + gID + "/emojis" }
EndpointGuildEmoji = func(gID, eID string) string { return EndpointGuilds + gID + "/emojis/" + eID }
EndpointGuildBanner = func(gID, hash string) string { return EndpointCDNBanners + gID + "/" + hash + ".png" }
+ EndpointGuildBannerAnimated = func(gID, hash string) string { return EndpointCDNBanners + gID + "/" + hash + ".gif" }
EndpointGuildStickers = func(gID string) string { return EndpointGuilds + gID + "/stickers" }
EndpointGuildSticker = func(gID, sID string) string { return EndpointGuilds + gID + "/stickers/" + sID }
EndpointStageInstance = func(cID string) string { return EndpointStageInstances + "/" + cID }
@@ -197,8 +199,9 @@ var (
EndpointEmoji = func(eID string) string { return EndpointCDN + "emojis/" + eID + ".png" }
EndpointEmojiAnimated = func(eID string) string { return EndpointCDN + "emojis/" + eID + ".gif" }
- EndpointApplications = EndpointAPI + "applications"
- EndpointApplication = func(aID string) string { return EndpointApplications + "/" + aID }
+ EndpointApplications = EndpointAPI + "applications"
+ EndpointApplication = func(aID string) string { return EndpointApplications + "/" + aID }
+ EndpointApplicationRoleConnectionMetadata = func(aID string) string { return EndpointApplication(aID) + "/role-connections/metadata" }
EndpointOAuth2 = EndpointAPI + "oauth2/"
EndpointOAuth2Applications = EndpointOAuth2 + "applications"
diff --git a/vendor/github.com/bwmarrin/discordgo/events.go b/vendor/github.com/bwmarrin/discordgo/events.go
index e5d83b9b..6608ab6e 100644
--- a/vendor/github.com/bwmarrin/discordgo/events.go
+++ b/vendor/github.com/bwmarrin/discordgo/events.go
@@ -36,13 +36,13 @@ type Event struct {
// A Ready stores all data for the websocket READY event.
type Ready struct {
- Version int `json:"v"`
- SessionID string `json:"session_id"`
- User *User `json:"user"`
- Guilds []*Guild `json:"guilds"`
- PrivateChannels []*Channel `json:"private_channels"`
-
- // TODO: Application and Shard
+ Version int `json:"v"`
+ SessionID string `json:"session_id"`
+ User *User `json:"user"`
+ Shard *[2]int `json:"shard"`
+ Application *Application `json:"application"`
+ Guilds []*Guild `json:"guilds"`
+ PrivateChannels []*Channel `json:"private_channels"`
}
// ChannelCreate is the data for a ChannelCreate event.
@@ -150,6 +150,7 @@ type GuildMemberAdd struct {
// GuildMemberUpdate is the data for a GuildMemberUpdate event.
type GuildMemberUpdate struct {
*Member
+ BeforeUpdate *Member `json:"-"`
}
// GuildMemberRemove is the data for a GuildMemberRemove event.
diff --git a/vendor/github.com/bwmarrin/discordgo/interactions.go b/vendor/github.com/bwmarrin/discordgo/interactions.go
index 61a4e992..627e0c38 100644
--- a/vendor/github.com/bwmarrin/discordgo/interactions.go
+++ b/vendor/github.com/bwmarrin/discordgo/interactions.go
@@ -42,6 +42,7 @@ type ApplicationCommand struct {
DefaultPermission *bool `json:"default_permission,omitempty"`
DefaultMemberPermissions *int64 `json:"default_member_permissions,string,omitempty"`
DMPermission *bool `json:"dm_permission,omitempty"`
+ NSFW *bool `json:"nsfw,omitempty"`
// NOTE: Chat commands only. Otherwise it mustn't be set.
@@ -343,13 +344,22 @@ func (ApplicationCommandInteractionData) Type() InteractionType {
// MessageComponentInteractionData contains the data of message component interaction.
type MessageComponentInteractionData struct {
- CustomID string `json:"custom_id"`
- ComponentType ComponentType `json:"component_type"`
+ CustomID string `json:"custom_id"`
+ ComponentType ComponentType `json:"component_type"`
+ Resolved MessageComponentInteractionDataResolved `json:"resolved"`
// NOTE: Only filled when ComponentType is SelectMenuComponent (3). Otherwise is nil.
Values []string `json:"values"`
}
+// MessageComponentInteractionDataResolved contains the resolved data of selected option.
+type MessageComponentInteractionDataResolved struct {
+ Users map[string]*User `json:"users"`
+ Members map[string]*Member `json:"members"`
+ Roles map[string]*Role `json:"roles"`
+ Channels map[string]*Channel `json:"channels"`
+}
+
// Type returns the type of interaction data.
func (MessageComponentInteractionData) Type() InteractionType {
return InteractionMessageComponent
@@ -472,7 +482,7 @@ func (o ApplicationCommandInteractionDataOption) RoleValue(s *Session, gID strin
return &Role{ID: roleID}
}
- r, err := s.State.Role(roleID, gID)
+ r, err := s.State.Role(gID, roleID)
if err != nil {
roles, err := s.GuildRoles(gID)
if err == nil {
diff --git a/vendor/github.com/bwmarrin/discordgo/message.go b/vendor/github.com/bwmarrin/discordgo/message.go
index 1ba6e445..fec6f879 100644
--- a/vendor/github.com/bwmarrin/discordgo/message.go
+++ b/vendor/github.com/bwmarrin/discordgo/message.go
@@ -249,6 +249,10 @@ type MessageEdit struct {
Embeds []*MessageEmbed `json:"embeds"`
AllowedMentions *MessageAllowedMentions `json:"allowed_mentions,omitempty"`
Flags MessageFlags `json:"flags,omitempty"`
+ // Files to append to the message
+ Files []*File `json:"-"`
+ // Overwrite existing attachments
+ Attachments *[]*MessageAttachment `json:"attachments,omitempty"`
ID string
Channel string
@@ -385,8 +389,8 @@ type MessageEmbedAuthor struct {
// MessageEmbedField is a part of a MessageEmbed struct.
type MessageEmbedField struct {
- Name string `json:"name,omitempty"`
- Value string `json:"value,omitempty"`
+ Name string `json:"name"`
+ Value string `json:"value"`
Inline bool `json:"inline,omitempty"`
}
diff --git a/vendor/github.com/bwmarrin/discordgo/restapi.go b/vendor/github.com/bwmarrin/discordgo/restapi.go
index 79af4680..b7d323e7 100644
--- a/vendor/github.com/bwmarrin/discordgo/restapi.go
+++ b/vendor/github.com/bwmarrin/discordgo/restapi.go
@@ -26,6 +26,8 @@ import (
"strconv"
"strings"
"time"
+
+ "context"
)
// All error constants
@@ -92,13 +94,82 @@ func (e RateLimitError) Error() string {
return "Rate limit exceeded on " + e.URL + ", retry after " + e.RetryAfter.String()
}
+// RequestConfig is an HTTP request configuration.
+type RequestConfig struct {
+ Request *http.Request
+ ShouldRetryOnRateLimit bool
+ MaxRestRetries int
+ Client *http.Client
+}
+
+// newRequestConfig returns a new HTTP request configuration based on parameters in Session.
+func newRequestConfig(s *Session, req *http.Request) *RequestConfig {
+ return &RequestConfig{
+ ShouldRetryOnRateLimit: s.ShouldRetryOnRateLimit,
+ MaxRestRetries: s.MaxRestRetries,
+ Client: s.Client,
+ Request: req,
+ }
+}
+
+// RequestOption is a function which mutates request configuration.
+// It can be supplied as an argument to any REST method.
+type RequestOption func(cfg *RequestConfig)
+
+// WithClient changes the HTTP client used for the request.
+func WithClient(client *http.Client) RequestOption {
+ return func(cfg *RequestConfig) {
+ if client != nil {
+ cfg.Client = client
+ }
+ }
+}
+
+// WithRetryOnRatelimit controls whether session will retry the request on rate limit.
+func WithRetryOnRatelimit(retry bool) RequestOption {
+ return func(cfg *RequestConfig) {
+ cfg.ShouldRetryOnRateLimit = retry
+ }
+}
+
+// WithRestRetries changes maximum amount of retries if request fails.
+func WithRestRetries(max int) RequestOption {
+ return func(cfg *RequestConfig) {
+ cfg.MaxRestRetries = max
+ }
+}
+
+// WithHeader sets a header in the request.
+func WithHeader(key, value string) RequestOption {
+ return func(cfg *RequestConfig) {
+ cfg.Request.Header.Set(key, value)
+ }
+}
+
+// WithAuditLogReason changes audit log reason associated with the request.
+func WithAuditLogReason(reason string) RequestOption {
+ return WithHeader("X-Audit-Log-Reason", reason)
+}
+
+// WithLocale changes accepted locale of the request.
+func WithLocale(locale Locale) RequestOption {
+ return WithHeader("X-Discord-Locale", string(locale))
+}
+
+// WithContext changes context of the request.
+func WithContext(ctx context.Context) RequestOption {
+ return func(cfg *RequestConfig) {
+ cfg.Request = cfg.Request.WithContext(ctx)
+ }
+}
+
// Request is the same as RequestWithBucketID but the bucket id is the same as the urlStr
-func (s *Session) Request(method, urlStr string, data interface{}) (response []byte, err error) {
- return s.RequestWithBucketID(method, urlStr, data, strings.SplitN(urlStr, "?", 2)[0])
+func (s *Session) Request(method, urlStr string, data interface{}, options ...RequestOption) (response []byte, err error) {
+ return s.RequestWithBucketID(method, urlStr, data, strings.SplitN(urlStr, "?", 2)[0], options...)
}
// RequestWithBucketID makes a (GET/POST/...) Requests to Discord REST API with JSON data.
-func (s *Session) RequestWithBucketID(method, urlStr string, data interface{}, bucketID string) (response []byte, err error) {
+func (s *Session) RequestWithBucketID(method, urlStr string, data interface{}, bucketID string, options ...RequestOption) (response []byte, err error) {
var body []byte
if data != nil {
body, err = Marshal(data)
@@ -107,21 +178,21 @@ func (s *Session) RequestWithBucketID(method, urlStr string, data interface{}, b
}
}
- return s.request(method, urlStr, "application/json", body, bucketID, 0)
+ return s.request(method, urlStr, "application/json", body, bucketID, 0, options...)
}
// request makes a (GET/POST/...) Requests to Discord REST API.
// Sequence is the sequence number, if it fails with a 502 it will
// retry with sequence+1 until it either succeeds or sequence >= session.MaxRestRetries
-func (s *Session) request(method, urlStr, contentType string, b []byte, bucketID string, sequence int) (response []byte, err error) {
+func (s *Session) request(method, urlStr, contentType string, b []byte, bucketID string, sequence int, options ...RequestOption) (response []byte, err error) {
if bucketID == "" {
bucketID = strings.SplitN(urlStr, "?", 2)[0]
}
- return s.RequestWithLockedBucket(method, urlStr, contentType, b, s.Ratelimiter.LockBucket(bucketID), sequence)
+ return s.RequestWithLockedBucket(method, urlStr, contentType, b, s.Ratelimiter.LockBucket(bucketID), sequence, options...)
}
// RequestWithLockedBucket makes a request using a bucket that's already been locked
-func (s *Session) RequestWithLockedBucket(method, urlStr, contentType string, b []byte, bucket *Bucket, sequence int) (response []byte, err error) {
+func (s *Session) RequestWithLockedBucket(method, urlStr, contentType string, b []byte, bucket *Bucket, sequence int, options ...RequestOption) (response []byte, err error) {
if s.Debug {
log.Printf("API REQUEST %8s :: %s\n", method, urlStr)
log.Printf("API REQUEST PAYLOAD :: [%s]\n", string(b))
@@ -148,13 +219,18 @@ func (s *Session) RequestWithLockedBucket(method, urlStr, contentType string, b
// TODO: Make a configurable static variable.
req.Header.Set("User-Agent", s.UserAgent)
+ cfg := newRequestConfig(s, req)
+ for _, opt := range options {
+ opt(cfg)
+ }
+
if s.Debug {
for k, v := range req.Header {
log.Printf("API REQUEST HEADER :: [%s] = %+v\n", k, v)
}
}
- resp, err := s.Client.Do(req)
+ resp, err := cfg.Client.Do(req)
if err != nil {
bucket.Release(nil)
return
@@ -191,10 +267,10 @@ func (s *Session) RequestWithLockedBucket(method, urlStr, contentType string, b
case http.StatusNoContent:
case http.StatusBadGateway:
// Retry sending request if possible
- if sequence < s.MaxRestRetries {
+ if sequence < cfg.MaxRestRetries {
s.log(LogInformational, "%s Failed (%s), Retrying...", urlStr, resp.Status)
- response, err = s.RequestWithLockedBucket(method, urlStr, contentType, b, s.Ratelimiter.LockBucketObject(bucket), sequence+1)
+ response, err = s.RequestWithLockedBucket(method, urlStr, contentType, b, s.Ratelimiter.LockBucketObject(bucket), sequence+1, options...)
} else {
err = fmt.Errorf("Exceeded Max retries HTTP %s, %s", resp.Status, response)
}
@@ -206,7 +282,7 @@ func (s *Session) RequestWithLockedBucket(method, urlStr, contentType string, b
return
}
- if s.ShouldRetryOnRateLimit {
+ if cfg.ShouldRetryOnRateLimit {
s.log(LogInformational, "Rate Limiting %s, retry in %v", urlStr, rl.RetryAfter)
s.handleEvent(rateLimitEventType, &RateLimit{TooManyRequests: &rl, URL: urlStr})
@@ -214,7 +290,7 @@ func (s *Session) RequestWithLockedBucket(method, urlStr, contentType string, b
// we can make the above smarter
// this method can cause longer delays than required
- response, err = s.RequestWithLockedBucket(method, urlStr, contentType, b, s.Ratelimiter.LockBucketObject(bucket), sequence)
+ response, err = s.RequestWithLockedBucket(method, urlStr, contentType, b, s.Ratelimiter.LockBucketObject(bucket), sequence, options...)
} else {
err = &RateLimitError{&RateLimit{TooManyRequests: &rl, URL: urlStr}}
}
@@ -246,9 +322,9 @@ func unmarshal(data []byte, v interface{}) error {
// User returns the user details of the given userID
// userID : A user ID or "@me" which is a shortcut of current user ID
-func (s *Session) User(userID string) (st *User, err error) {
+func (s *Session) User(userID string, options ...RequestOption) (st *User, err error) {
- body, err := s.RequestWithBucketID("GET", EndpointUser(userID), nil, EndpointUsers)
+ body, err := s.RequestWithBucketID("GET", EndpointUser(userID), nil, EndpointUsers, options...)
if err != nil {
return
}
@@ -259,19 +335,19 @@ func (s *Session) User(userID string) (st *User, err error) {
// UserAvatar is deprecated. Please use UserAvatarDecode
// userID : A user ID or "@me" which is a shortcut of current user ID
-func (s *Session) UserAvatar(userID string) (img image.Image, err error) {
- u, err := s.User(userID)
+func (s *Session) UserAvatar(userID string, options ...RequestOption) (img image.Image, err error) {
+ u, err := s.User(userID, options...)
if err != nil {
return
}
- img, err = s.UserAvatarDecode(u)
+ img, err = s.UserAvatarDecode(u, options...)
return
}
// UserAvatarDecode returns an image.Image of a user's Avatar
// user : The user which avatar should be retrieved
-func (s *Session) UserAvatarDecode(u *User) (img image.Image, err error) {
- body, err := s.RequestWithBucketID("GET", EndpointUserAvatar(u.ID, u.Avatar), nil, EndpointUserAvatar("", ""))
+func (s *Session) UserAvatarDecode(u *User, options ...RequestOption) (img image.Image, err error) {
+ body, err := s.RequestWithBucketID("GET", EndpointUserAvatar(u.ID, u.Avatar), nil, EndpointUserAvatar("", ""), options...)
if err != nil {
return
}
@@ -281,7 +357,7 @@ func (s *Session) UserAvatarDecode(u *User) (img image.Image, err error) {
}
// UserUpdate updates current user settings.
-func (s *Session) UserUpdate(username, avatar string) (st *User, err error) {
+func (s *Session) UserUpdate(username, avatar string, options ...RequestOption) (st *User, err error) {
// NOTE: Avatar must be either the hash/id of existing Avatar or
// data:image/png;base64,BASE64_STRING_OF_NEW_AVATAR_PNG
@@ -293,7 +369,7 @@ func (s *Session) UserUpdate(username, avatar string) (st *User, err error) {
Avatar string `json:"avatar,omitempty"`
}{username, avatar}
- body, err := s.RequestWithBucketID("PATCH", EndpointUser("@me"), data, EndpointUsers)
+ body, err := s.RequestWithBucketID("PATCH", EndpointUser("@me"), data, EndpointUsers, options...)
if err != nil {
return
}
@@ -303,8 +379,8 @@ func (s *Session) UserUpdate(username, avatar string) (st *User, err error) {
}
// UserConnections returns the user's connections
-func (s *Session) UserConnections() (conn []*UserConnection, err error) {
- response, err := s.RequestWithBucketID("GET", EndpointUserConnections("@me"), nil, EndpointUserConnections("@me"))
+func (s *Session) UserConnections(options ...RequestOption) (conn []*UserConnection, err error) {
+ response, err := s.RequestWithBucketID("GET", EndpointUserConnections("@me"), nil, EndpointUserConnections("@me"), options...)
if err != nil {
return nil, err
}
@@ -319,13 +395,13 @@ func (s *Session) UserConnections() (conn []*UserConnection, err error) {
// UserChannelCreate creates a new User (Private) Channel with another User
// recipientID : A user ID for the user to which this channel is opened with.
-func (s *Session) UserChannelCreate(recipientID string) (st *Channel, err error) {
+func (s *Session) UserChannelCreate(recipientID string, options ...RequestOption) (st *Channel, err error) {
data := struct {
RecipientID string `json:"recipient_id"`
}{recipientID}
- body, err := s.RequestWithBucketID("POST", EndpointUserChannels("@me"), data, EndpointUserChannels(""))
+ body, err := s.RequestWithBucketID("POST", EndpointUserChannels("@me"), data, EndpointUserChannels(""), options...)
if err != nil {
return
}
@@ -336,8 +412,8 @@ func (s *Session) UserChannelCreate(recipientID string) (st *Channel, err error)
// UserGuildMember returns a guild member object for the current user in the given Guild.
// guildID : ID of the guild
-func (s *Session) UserGuildMember(guildID string) (st *Member, err error) {
- body, err := s.RequestWithBucketID("GET", EndpointUserGuildMember("@me", guildID), nil, EndpointUserGuildMember("@me", guildID))
+func (s *Session) UserGuildMember(guildID string, options ...RequestOption) (st *Member, err error) {
+ body, err := s.RequestWithBucketID("GET", EndpointUserGuildMember("@me", guildID), nil, EndpointUserGuildMember("@me", guildID), options...)
if err != nil {
return
}
@@ -350,7 +426,7 @@ func (s *Session) UserGuildMember(guildID string) (st *Member, err error) {
// limit : The number guilds that can be returned. (max 100)
// beforeID : If provided all guilds returned will be before given ID.
// afterID : If provided all guilds returned will be after given ID.
-func (s *Session) UserGuilds(limit int, beforeID, afterID string) (st []*UserGuild, err error) {
+func (s *Session) UserGuilds(limit int, beforeID, afterID string, options ...RequestOption) (st []*UserGuild, err error) {
v := url.Values{}
@@ -370,7 +446,7 @@ func (s *Session) UserGuilds(limit int, beforeID, afterID string) (st []*UserGui
uri += "?" + v.Encode()
}
- body, err := s.RequestWithBucketID("GET", uri, nil, EndpointUserGuilds(""))
+ body, err := s.RequestWithBucketID("GET", uri, nil, EndpointUserGuilds(""), options...)
if err != nil {
return
}
@@ -380,12 +456,13 @@ func (s *Session) UserGuilds(limit int, beforeID, afterID string) (st []*UserGui
}
// UserChannelPermissions returns the permission of a user in a channel.
-// userID : The ID of the user to calculate permissions for.
-// channelID : The ID of the channel to calculate permission for.
+// userID : The ID of the user to calculate permissions for.
+// channelID : The ID of the channel to calculate permission for.
+// fetchOptions : Options used to fetch guild, member or channel if they are not present in state.
//
// NOTE: This function is now deprecated and will be removed in the future.
// Please see the same function inside state.go
-func (s *Session) UserChannelPermissions(userID, channelID string) (apermissions int64, err error) {
+func (s *Session) UserChannelPermissions(userID, channelID string, fetchOptions ...RequestOption) (apermissions int64, err error) {
// Try to just get permissions from state.
apermissions, err = s.State.UserChannelPermissions(userID, channelID)
if err == nil {
@@ -395,7 +472,7 @@ func (s *Session) UserChannelPermissions(userID, channelID string) (apermissions
// Otherwise try get as much data from state as possible, falling back to the network.
channel, err := s.State.Channel(channelID)
if err != nil || channel == nil {
- channel, err = s.Channel(channelID)
+ channel, err = s.Channel(channelID, fetchOptions...)
if err != nil {
return
}
@@ -403,7 +480,7 @@ func (s *Session) UserChannelPermissions(userID, channelID string) (apermissions
guild, err := s.State.Guild(channel.GuildID)
if err != nil || guild == nil {
- guild, err = s.Guild(channel.GuildID)
+ guild, err = s.Guild(channel.GuildID, fetchOptions...)
if err != nil {
return
}
@@ -416,7 +493,7 @@ func (s *Session) UserChannelPermissions(userID, channelID string) (apermissions
member, err := s.State.Member(guild.ID, userID)
if err != nil || member == nil {
- member, err = s.GuildMember(guild.ID, userID)
+ member, err = s.GuildMember(guild.ID, userID, fetchOptions...)
if err != nil {
return
}
@@ -498,8 +575,8 @@ func memberPermissions(guild *Guild, channel *Channel, userID string, roles []st
// Guild returns a Guild structure of a specific Guild.
// guildID : The ID of a Guild
-func (s *Session) Guild(guildID string) (st *Guild, err error) {
- body, err := s.RequestWithBucketID("GET", EndpointGuild(guildID), nil, EndpointGuild(guildID))
+func (s *Session) Guild(guildID string, options ...RequestOption) (st *Guild, err error) {
+ body, err := s.RequestWithBucketID("GET", EndpointGuild(guildID), nil, EndpointGuild(guildID), options...)
if err != nil {
return
}
@@ -510,9 +587,9 @@ func (s *Session) Guild(guildID string) (st *Guild, err error) {
// GuildWithCounts returns a Guild structure of a specific Guild with approximate member and presence counts.
// guildID : The ID of a Guild
-func (s *Session) GuildWithCounts(guildID string) (st *Guild, err error) {
+func (s *Session) GuildWithCounts(guildID string, options ...RequestOption) (st *Guild, err error) {
- body, err := s.RequestWithBucketID("GET", EndpointGuild(guildID)+"?with_counts=true", nil, EndpointGuild(guildID))
+ body, err := s.RequestWithBucketID("GET", EndpointGuild(guildID)+"?with_counts=true", nil, EndpointGuild(guildID), options...)
if err != nil {
return
}
@@ -523,8 +600,8 @@ func (s *Session) GuildWithCounts(guildID string) (st *Guild, err error) {
// GuildPreview returns a GuildPreview structure of a specific public Guild.
// guildID : The ID of a Guild
-func (s *Session) GuildPreview(guildID string) (st *GuildPreview, err error) {
- body, err := s.RequestWithBucketID("GET", EndpointGuildPreview(guildID), nil, EndpointGuildPreview(guildID))
+func (s *Session) GuildPreview(guildID string, options ...RequestOption) (st *GuildPreview, err error) {
+ body, err := s.RequestWithBucketID("GET", EndpointGuildPreview(guildID), nil, EndpointGuildPreview(guildID), options...)
if err != nil {
return
}
@@ -535,13 +612,13 @@ func (s *Session) GuildPreview(guildID string) (st *GuildPreview, err error) {
// GuildCreate creates a new Guild
// name : A name for the Guild (2-100 characters)
-func (s *Session) GuildCreate(name string) (st *Guild, err error) {
+func (s *Session) GuildCreate(name string, options ...RequestOption) (st *Guild, err error) {
data := struct {
Name string `json:"name"`
}{name}
- body, err := s.RequestWithBucketID("POST", EndpointGuildCreate, data, EndpointGuildCreate)
+ body, err := s.RequestWithBucketID("POST", EndpointGuildCreate, data, EndpointGuildCreate, options...)
if err != nil {
return
}
@@ -553,7 +630,7 @@ func (s *Session) GuildCreate(name string) (st *Guild, err error) {
// GuildEdit edits a new Guild
// guildID : The ID of a Guild
// g : A GuildParams struct with the values Name, Region and VerificationLevel defined.
-func (s *Session) GuildEdit(guildID string, g *GuildParams) (st *Guild, err error) {
+func (s *Session) GuildEdit(guildID string, g *GuildParams, options ...RequestOption) (st *Guild, err error) {
// Bounds checking for VerificationLevel, interval: [0, 4]
if g.VerificationLevel != nil {
@@ -567,7 +644,7 @@ func (s *Session) GuildEdit(guildID string, g *GuildParams) (st *Guild, err erro
// Bounds checking for regions
if g.Region != "" {
isValid := false
- regions, _ := s.VoiceRegions()
+ regions, _ := s.VoiceRegions(options...)
for _, r := range regions {
if g.Region == r.ID {
isValid = true
@@ -583,7 +660,7 @@ func (s *Session) GuildEdit(guildID string, g *GuildParams) (st *Guild, err erro
}
}
- body, err := s.RequestWithBucketID("PATCH", EndpointGuild(guildID), g, EndpointGuild(guildID))
+ body, err := s.RequestWithBucketID("PATCH", EndpointGuild(guildID), g, EndpointGuild(guildID), options...)
if err != nil {
return
}
@@ -594,9 +671,9 @@ func (s *Session) GuildEdit(guildID string, g *GuildParams) (st *Guild, err erro
// GuildDelete deletes a Guild.
// guildID : The ID of a Guild
-func (s *Session) GuildDelete(guildID string) (st *Guild, err error) {
+func (s *Session) GuildDelete(guildID string, options ...RequestOption) (st *Guild, err error) {
- body, err := s.RequestWithBucketID("DELETE", EndpointGuild(guildID), nil, EndpointGuild(guildID))
+ body, err := s.RequestWithBucketID("DELETE", EndpointGuild(guildID), nil, EndpointGuild(guildID), options...)
if err != nil {
return
}
@@ -607,18 +684,18 @@ func (s *Session) GuildDelete(guildID string) (st *Guild, err error) {
// GuildLeave leaves a Guild.
// guildID : The ID of a Guild
-func (s *Session) GuildLeave(guildID string) (err error) {
+func (s *Session) GuildLeave(guildID string, options ...RequestOption) (err error) {
- _, err = s.RequestWithBucketID("DELETE", EndpointUserGuild("@me", guildID), nil, EndpointUserGuild("", guildID))
+ _, err = s.RequestWithBucketID("DELETE", EndpointUserGuild("@me", guildID), nil, EndpointUserGuild("", guildID), options...)
return
}
// GuildBans returns an array of GuildBan structures for bans in the given guild.
-// guildID : The ID of a Guild
-// limit : Max number of bans to return (max 1000)
-// beforeID : If not empty all returned users will be after the given id
-// afterID : If not empty all returned users will be before the given id
-func (s *Session) GuildBans(guildID string, limit int, beforeID, afterID string) (st []*GuildBan, err error) {
+// guildID : The ID of a Guild
+// limit : Max number of bans to return (max 1000)
+// beforeID : If not empty all returned users will be after the given id
+// afterID : If not empty all returned users will be before the given id
+func (s *Session) GuildBans(guildID string, limit int, beforeID, afterID string, options ...RequestOption) (st []*GuildBan, err error) {
uri := EndpointGuildBans(guildID)
v := url.Values{}
@@ -636,7 +713,7 @@ func (s *Session) GuildBans(guildID string, limit int, beforeID, afterID string)
uri += "?" + v.Encode()
}
- body, err := s.RequestWithBucketID("GET", uri, nil, EndpointGuildBans(guildID))
+ body, err := s.RequestWithBucketID("GET", uri, nil, EndpointGuildBans(guildID), options...)
if err != nil {
return
}
@@ -650,14 +727,14 @@ func (s *Session) GuildBans(guildID string, limit int, beforeID, afterID string)
// guildID : The ID of a Guild.
// userID : The ID of a User
// days : The number of days of previous comments to delete.
-func (s *Session) GuildBanCreate(guildID, userID string, days int) (err error) {
- return s.GuildBanCreateWithReason(guildID, userID, "", days)
+func (s *Session) GuildBanCreate(guildID, userID string, days int, options ...RequestOption) (err error) {
+ return s.GuildBanCreateWithReason(guildID, userID, "", days, options...)
}
// GuildBan finds ban by given guild and user id and returns GuildBan structure
-func (s *Session) GuildBan(guildID, userID string) (st *GuildBan, err error) {
+func (s *Session) GuildBan(guildID, userID string, options ...RequestOption) (st *GuildBan, err error) {
- body, err := s.RequestWithBucketID("GET", EndpointGuildBan(guildID, userID), nil, EndpointGuildBan(guildID, userID))
+ body, err := s.RequestWithBucketID("GET", EndpointGuildBan(guildID, userID), nil, EndpointGuildBan(guildID, userID), options...)
if err != nil {
return
}
@@ -672,7 +749,7 @@ func (s *Session) GuildBan(guildID, userID string) (st *GuildBan, err error) {
// userID : The ID of a User
// reason : The reason for this ban
// days : The number of days of previous comments to delete.
-func (s *Session) GuildBanCreateWithReason(guildID, userID, reason string, days int) (err error) {
+func (s *Session) GuildBanCreateWithReason(guildID, userID, reason string, days int, options ...RequestOption) (err error) {
uri := EndpointGuildBan(guildID, userID)
@@ -688,24 +765,24 @@ func (s *Session) GuildBanCreateWithReason(guildID, userID, reason string, days
uri += "?" + queryParams.Encode()
}
- _, err = s.RequestWithBucketID("PUT", uri, nil, EndpointGuildBan(guildID, ""))
+ _, err = s.RequestWithBucketID("PUT", uri, nil, EndpointGuildBan(guildID, ""), options...)
return
}
// GuildBanDelete removes the given user from the guild bans
// guildID : The ID of a Guild.
// userID : The ID of a User
-func (s *Session) GuildBanDelete(guildID, userID string) (err error) {
+func (s *Session) GuildBanDelete(guildID, userID string, options ...RequestOption) (err error) {
- _, err = s.RequestWithBucketID("DELETE", EndpointGuildBan(guildID, userID), nil, EndpointGuildBan(guildID, ""))
+ _, err = s.RequestWithBucketID("DELETE", EndpointGuildBan(guildID, userID), nil, EndpointGuildBan(guildID, ""), options...)
return
}
// GuildMembers returns a list of members for a guild.
-// guildID : The ID of a Guild.
-// after : The id of the member to return members after
-// limit : max number of members to return (max 1000)
-func (s *Session) GuildMembers(guildID string, after string, limit int) (st []*Member, err error) {
+// guildID : The ID of a Guild.
+// after : The id of the member to return members after
+// limit : max number of members to return (max 1000)
+func (s *Session) GuildMembers(guildID string, after string, limit int, options ...RequestOption) (st []*Member, err error) {
uri := EndpointGuildMembers(guildID)
@@ -723,7 +800,7 @@ func (s *Session) GuildMembers(guildID string, after string, limit int) (st []*M
uri += "?" + v.Encode()
}
- body, err := s.RequestWithBucketID("GET", uri, nil, EndpointGuildMembers(guildID))
+ body, err := s.RequestWithBucketID("GET", uri, nil, EndpointGuildMembers(guildID), options...)
if err != nil {
return
}
@@ -736,7 +813,7 @@ func (s *Session) GuildMembers(guildID string, after string, limit int) (st []*M
// guildID : The ID of a Guild
// query : Query string to match username(s) and nickname(s) against
// limit : Max number of members to return (default 1, min 1, max 1000)
-func (s *Session) GuildMembersSearch(guildID, query string, limit int) (st []*Member, err error) {
+func (s *Session) GuildMembersSearch(guildID, query string, limit int, options ...RequestOption) (st []*Member, err error) {
uri := EndpointGuildMembersSearch(guildID)
@@ -746,7 +823,7 @@ func (s *Session) GuildMembersSearch(guildID, query string, limit int) (st []*Me
queryParams.Set("limit", strconv.Itoa(limit))
}
- body, err := s.RequestWithBucketID("GET", uri+"?"+queryParams.Encode(), nil, uri)
+ body, err := s.RequestWithBucketID("GET", uri+"?"+queryParams.Encode(), nil, uri, options...)
if err != nil {
return
}
@@ -756,11 +833,11 @@ func (s *Session) GuildMembersSearch(guildID, query string, limit int) (st []*Me
}
// GuildMember returns a member of a guild.
-// guildID : The ID of a Guild.
-// userID : The ID of a User
-func (s *Session) GuildMember(guildID, userID string) (st *Member, err error) {
+// guildID : The ID of a Guild.
+// userID : The ID of a User
+func (s *Session) GuildMember(guildID, userID string, options ...RequestOption) (st *Member, err error) {
- body, err := s.RequestWithBucketID("GET", EndpointGuildMember(guildID, userID), nil, EndpointGuildMember(guildID, ""))
+ body, err := s.RequestWithBucketID("GET", EndpointGuildMember(guildID, userID), nil, EndpointGuildMember(guildID, ""), options...)
if err != nil {
return
}
@@ -772,12 +849,12 @@ func (s *Session) GuildMember(guildID, userID string) (st *Member, err error) {
}
// GuildMemberAdd force joins a user to the guild.
-// guildID : The ID of a Guild.
-// userID : The ID of a User.
-// data : Parameters of the user to add.
-func (s *Session) GuildMemberAdd(guildID, userID string, data *GuildMemberAddParams) (err error) {
+// guildID : The ID of a Guild.
+// userID : The ID of a User.
+// data : Parameters of the user to add.
+func (s *Session) GuildMemberAdd(guildID, userID string, data *GuildMemberAddParams, options ...RequestOption) (err error) {
- _, err = s.RequestWithBucketID("PUT", EndpointGuildMember(guildID, userID), data, EndpointGuildMember(guildID, ""))
+ _, err = s.RequestWithBucketID("PUT", EndpointGuildMember(guildID, userID), data, EndpointGuildMember(guildID, ""), options...)
if err != nil {
return err
}
@@ -788,23 +865,23 @@ func (s *Session) GuildMemberAdd(guildID, userID string, data *GuildMemberAddPar
// GuildMemberDelete removes the given user from the given guild.
// guildID : The ID of a Guild.
// userID : The ID of a User
-func (s *Session) GuildMemberDelete(guildID, userID string) (err error) {
+func (s *Session) GuildMemberDelete(guildID, userID string, options ...RequestOption) (err error) {
- return s.GuildMemberDeleteWithReason(guildID, userID, "")
+ return s.GuildMemberDeleteWithReason(guildID, userID, "", options...)
}
// GuildMemberDeleteWithReason removes the given user from the given guild.
// guildID : The ID of a Guild.
// userID : The ID of a User
// reason : The reason for the kick
-func (s *Session) GuildMemberDeleteWithReason(guildID, userID, reason string) (err error) {
+func (s *Session) GuildMemberDeleteWithReason(guildID, userID, reason string, options ...RequestOption) (err error) {
uri := EndpointGuildMember(guildID, userID)
if reason != "" {
uri += "?reason=" + url.QueryEscape(reason)
}
- _, err = s.RequestWithBucketID("DELETE", uri, nil, EndpointGuildMember(guildID, ""))
+ _, err = s.RequestWithBucketID("DELETE", uri, nil, EndpointGuildMember(guildID, ""), options...)
return
}
@@ -812,9 +889,9 @@ func (s *Session) GuildMemberDeleteWithReason(guildID, userID, reason string) (e
// guildID : The ID of a Guild.
// userID : The ID of a User.
// data : Updated GuildMember data.
-func (s *Session) GuildMemberEdit(guildID, userID string, data *GuildMemberParams) (st *Member, err error) {
+func (s *Session) GuildMemberEdit(guildID, userID string, data *GuildMemberParams, options ...RequestOption) (st *Member, err error) {
var body []byte
- body, err = s.RequestWithBucketID("PATCH", EndpointGuildMember(guildID, userID), data, EndpointGuildMember(guildID, ""))
+ body, err = s.RequestWithBucketID("PATCH", EndpointGuildMember(guildID, userID), data, EndpointGuildMember(guildID, ""), options...)
if err != nil {
return nil, err
}
@@ -825,25 +902,27 @@ func (s *Session) GuildMemberEdit(guildID, userID string, data *GuildMemberParam
// GuildMemberEditComplex edits the nickname and roles of a member.
// NOTE: deprecated, use GuildMemberEdit instead.
+//
// guildID : The ID of a Guild.
// userID : The ID of a User.
// data : A GuildMemberEditData struct with the new nickname and roles
-func (s *Session) GuildMemberEditComplex(guildID, userID string, data *GuildMemberParams) (st *Member, err error) {
- return s.GuildMemberEdit(guildID, userID, data)
+func (s *Session) GuildMemberEditComplex(guildID, userID string, data *GuildMemberParams, options ...RequestOption) (st *Member, err error) {
+ return s.GuildMemberEdit(guildID, userID, data, options...)
}
// GuildMemberMove moves a guild member from one voice channel to another/none
-// guildID : The ID of a Guild.
-// userID : The ID of a User.
-// channelID : The ID of a channel to move user to or nil to remove from voice channel
+// guildID : The ID of a Guild.
+// userID : The ID of a User.
+// channelID : The ID of a channel to move user to or nil to remove from voice channel
+//
// NOTE : I am not entirely set on the name of this function and it may change
// prior to the final 1.0.0 release of Discordgo
-func (s *Session) GuildMemberMove(guildID string, userID string, channelID *string) (err error) {
+func (s *Session) GuildMemberMove(guildID string, userID string, channelID *string, options ...RequestOption) (err error) {
data := struct {
ChannelID *string `json:"channel_id"`
}{channelID}
- _, err = s.RequestWithBucketID("PATCH", EndpointGuildMember(guildID, userID), data, EndpointGuildMember(guildID, ""))
+ _, err = s.RequestWithBucketID("PATCH", EndpointGuildMember(guildID, userID), data, EndpointGuildMember(guildID, ""), options...)
return
}
@@ -852,7 +931,7 @@ func (s *Session) GuildMemberMove(guildID string, userID string, channelID *stri
// userID : The ID of a user
// userID : The ID of a user or "@me" which is a shortcut of the current user ID
// nickname : The nickname of the member, "" will reset their nickname
-func (s *Session) GuildMemberNickname(guildID, userID, nickname string) (err error) {
+func (s *Session) GuildMemberNickname(guildID, userID, nickname string, options ...RequestOption) (err error) {
data := struct {
Nick string `json:"nick"`
@@ -862,68 +941,67 @@ func (s *Session) GuildMemberNickname(guildID, userID, nickname string) (err err
userID += "/nick"
}
- _, err = s.RequestWithBucketID("PATCH", EndpointGuildMember(guildID, userID), data, EndpointGuildMember(guildID, ""))
+ _, err = s.RequestWithBucketID("PATCH", EndpointGuildMember(guildID, userID), data, EndpointGuildMember(guildID, ""), options...)
return
}
// GuildMemberMute server mutes a guild member
-// guildID : The ID of a Guild.
-// userID : The ID of a User.
-// mute : boolean value for if the user should be muted
-func (s *Session) GuildMemberMute(guildID string, userID string, mute bool) (err error) {
+// guildID : The ID of a Guild.
+// userID : The ID of a User.
+// mute : boolean value for if the user should be muted
+func (s *Session) GuildMemberMute(guildID string, userID string, mute bool, options ...RequestOption) (err error) {
data := struct {
Mute bool `json:"mute"`
}{mute}
- _, err = s.RequestWithBucketID("PATCH", EndpointGuildMember(guildID, userID), data, EndpointGuildMember(guildID, ""))
+ _, err = s.RequestWithBucketID("PATCH", EndpointGuildMember(guildID, userID), data, EndpointGuildMember(guildID, ""), options...)
return
}
// GuildMemberTimeout times out a guild member
-// guildID : The ID of a Guild.
-// userID : The ID of a User.
-// until : The timestamp for how long a member should be timed out.
-// Set to nil to remove timeout.
-func (s *Session) GuildMemberTimeout(guildID string, userID string, until *time.Time) (err error) {
+// guildID : The ID of a Guild.
+// userID : The ID of a User.
+// until : The timestamp for how long a member should be timed out. Set to nil to remove timeout.
+func (s *Session) GuildMemberTimeout(guildID string, userID string, until *time.Time, options ...RequestOption) (err error) {
data := struct {
CommunicationDisabledUntil *time.Time `json:"communication_disabled_until"`
}{until}
- _, err = s.RequestWithBucketID("PATCH", EndpointGuildMember(guildID, userID), data, EndpointGuildMember(guildID, ""))
+ _, err = s.RequestWithBucketID("PATCH", EndpointGuildMember(guildID, userID), data, EndpointGuildMember(guildID, ""), options...)
return
}
// GuildMemberDeafen server deafens a guild member
-// guildID : The ID of a Guild.
-// userID : The ID of a User.
-// deaf : boolean value for if the user should be deafened
-func (s *Session) GuildMemberDeafen(guildID string, userID string, deaf bool) (err error) {
+// guildID : The ID of a Guild.
+// userID : The ID of a User.
+// deaf : boolean value for if the user should be deafened
+func (s *Session) GuildMemberDeafen(guildID string, userID string, deaf bool, options ...RequestOption) (err error) {
data := struct {
Deaf bool `json:"deaf"`
}{deaf}
- _, err = s.RequestWithBucketID("PATCH", EndpointGuildMember(guildID, userID), data, EndpointGuildMember(guildID, ""))
+ _, err = s.RequestWithBucketID("PATCH", EndpointGuildMember(guildID, userID), data, EndpointGuildMember(guildID, ""), options...)
return
}
// GuildMemberRoleAdd adds the specified role to a given member
-// guildID : The ID of a Guild.
-// userID : The ID of a User.
-// roleID : The ID of a Role to be assigned to the user.
-func (s *Session) GuildMemberRoleAdd(guildID, userID, roleID string) (err error) {
+// guildID : The ID of a Guild.
+// userID : The ID of a User.
+// roleID : The ID of a Role to be assigned to the user.
+func (s *Session) GuildMemberRoleAdd(guildID, userID, roleID string, options ...RequestOption) (err error) {
- _, err = s.RequestWithBucketID("PUT", EndpointGuildMemberRole(guildID, userID, roleID), nil, EndpointGuildMemberRole(guildID, "", ""))
+ _, err = s.RequestWithBucketID("PUT", EndpointGuildMemberRole(guildID, userID, roleID), nil, EndpointGuildMemberRole(guildID, "", ""), options...)
return
}
// GuildMemberRoleRemove removes the specified role to a given member
-// guildID : The ID of a Guild.
-// userID : The ID of a User.
-// roleID : The ID of a Role to be removed from the user.
-func (s *Session) GuildMemberRoleRemove(guildID, userID, roleID string) (err error) {
+// guildID : The ID of a Guild.
+// userID : The ID of a User.
+// roleID : The ID of a Role to be removed from the user.
+func (s *Session) GuildMemberRoleRemove(guildID, userID, roleID string, options ...RequestOption) (err error) {
- _, err = s.RequestWithBucketID("DELETE", EndpointGuildMemberRole(guildID, userID, roleID), nil, EndpointGuildMemberRole(guildID, "", ""))
+ _, err = s.RequestWithBucketID("DELETE", EndpointGuildMemberRole(guildID, userID, roleID), nil, EndpointGuildMemberRole(guildID, "", ""), options...)
return
}
@@ -931,9 +1009,9 @@ func (s *Session) GuildMemberRoleRemove(guildID, userID, roleID string) (err err
// GuildChannels returns an array of Channel structures for all channels of a
// given guild.
// guildID : The ID of a Guild.
-func (s *Session) GuildChannels(guildID string) (st []*Channel, err error) {
+func (s *Session) GuildChannels(guildID string, options ...RequestOption) (st []*Channel, err error) {
- body, err := s.request("GET", EndpointGuildChannels(guildID), "", nil, EndpointGuildChannels(guildID), 0)
+ body, err := s.request("GET", EndpointGuildChannels(guildID), "", nil, EndpointGuildChannels(guildID), 0, options...)
if err != nil {
return
}
@@ -960,8 +1038,8 @@ type GuildChannelCreateData struct {
// GuildChannelCreateComplex creates a new channel in the given guild
// guildID : The ID of a Guild
// data : A data struct describing the new Channel, Name and Type are mandatory, other fields depending on the type
-func (s *Session) GuildChannelCreateComplex(guildID string, data GuildChannelCreateData) (st *Channel, err error) {
- body, err := s.RequestWithBucketID("POST", EndpointGuildChannels(guildID), data, EndpointGuildChannels(guildID))
+func (s *Session) GuildChannelCreateComplex(guildID string, data GuildChannelCreateData, options ...RequestOption) (st *Channel, err error) {
+ body, err := s.RequestWithBucketID("POST", EndpointGuildChannels(guildID), data, EndpointGuildChannels(guildID), options...)
if err != nil {
return
}
@@ -974,17 +1052,17 @@ func (s *Session) GuildChannelCreateComplex(guildID string, data GuildChannelCre
// guildID : The ID of a Guild.
// name : Name of the channel (2-100 chars length)
// ctype : Type of the channel
-func (s *Session) GuildChannelCreate(guildID, name string, ctype ChannelType) (st *Channel, err error) {
+func (s *Session) GuildChannelCreate(guildID, name string, ctype ChannelType, options ...RequestOption) (st *Channel, err error) {
return s.GuildChannelCreateComplex(guildID, GuildChannelCreateData{
Name: name,
Type: ctype,
- })
+ }, options...)
}
// GuildChannelsReorder updates the order of channels in a guild
// guildID : The ID of a Guild.
// channels : Updated channels.
-func (s *Session) GuildChannelsReorder(guildID string, channels []*Channel) (err error) {
+func (s *Session) GuildChannelsReorder(guildID string, channels []*Channel, options ...RequestOption) (err error) {
data := make([]struct {
ID string `json:"id"`
@@ -996,14 +1074,14 @@ func (s *Session) GuildChannelsReorder(guildID string, channels []*Channel) (err
data[i].Position = c.Position
}
- _, err = s.RequestWithBucketID("PATCH", EndpointGuildChannels(guildID), data, EndpointGuildChannels(guildID))
+ _, err = s.RequestWithBucketID("PATCH", EndpointGuildChannels(guildID), data, EndpointGuildChannels(guildID), options...)
return
}
// GuildInvites returns an array of Invite structures for the given guild
// guildID : The ID of a Guild.
-func (s *Session) GuildInvites(guildID string) (st []*Invite, err error) {
- body, err := s.RequestWithBucketID("GET", EndpointGuildInvites(guildID), nil, EndpointGuildInvites(guildID))
+func (s *Session) GuildInvites(guildID string, options ...RequestOption) (st []*Invite, err error) {
+ body, err := s.RequestWithBucketID("GET", EndpointGuildInvites(guildID), nil, EndpointGuildInvites(guildID), options...)
if err != nil {
return
}
@@ -1014,9 +1092,9 @@ func (s *Session) GuildInvites(guildID string) (st []*Invite, err error) {
// GuildRoles returns all roles for a given guild.
// guildID : The ID of a Guild.
-func (s *Session) GuildRoles(guildID string) (st []*Role, err error) {
+func (s *Session) GuildRoles(guildID string, options ...RequestOption) (st []*Role, err error) {
- body, err := s.RequestWithBucketID("GET", EndpointGuildRoles(guildID), nil, EndpointGuildRoles(guildID))
+ body, err := s.RequestWithBucketID("GET", EndpointGuildRoles(guildID), nil, EndpointGuildRoles(guildID), options...)
if err != nil {
return
}
@@ -1029,8 +1107,8 @@ func (s *Session) GuildRoles(guildID string) (st []*Role, err error) {
// GuildRoleCreate creates a new Guild Role and returns it.
// guildID : The ID of a Guild.
// data : New Role parameters.
-func (s *Session) GuildRoleCreate(guildID string, data *RoleParams) (st *Role, err error) {
- body, err := s.RequestWithBucketID("POST", EndpointGuildRoles(guildID), data, EndpointGuildRoles(guildID))
+func (s *Session) GuildRoleCreate(guildID string, data *RoleParams, options ...RequestOption) (st *Role, err error) {
+ body, err := s.RequestWithBucketID("POST", EndpointGuildRoles(guildID), data, EndpointGuildRoles(guildID), options...)
if err != nil {
return
}
@@ -1044,14 +1122,14 @@ func (s *Session) GuildRoleCreate(guildID string, data *RoleParams) (st *Role, e
// guildID : The ID of a Guild.
// roleID : The ID of a Role.
// data : Updated Role data.
-func (s *Session) GuildRoleEdit(guildID, roleID string, data *RoleParams) (st *Role, err error) {
+func (s *Session) GuildRoleEdit(guildID, roleID string, data *RoleParams, options ...RequestOption) (st *Role, err error) {
// Prevent sending a color int that is too big.
if data.Color != nil && *data.Color > 0xFFFFFF {
return nil, fmt.Errorf("color value cannot be larger than 0xFFFFFF")
}
- body, err := s.RequestWithBucketID("PATCH", EndpointGuildRole(guildID, roleID), data, EndpointGuildRole(guildID, ""))
+ body, err := s.RequestWithBucketID("PATCH", EndpointGuildRole(guildID, roleID), data, EndpointGuildRole(guildID, ""), options...)
if err != nil {
return
}
@@ -1064,9 +1142,9 @@ func (s *Session) GuildRoleEdit(guildID, roleID string, data *RoleParams) (st *R
// GuildRoleReorder reoders guild roles
// guildID : The ID of a Guild.
// roles : A list of ordered roles.
-func (s *Session) GuildRoleReorder(guildID string, roles []*Role) (st []*Role, err error) {
+func (s *Session) GuildRoleReorder(guildID string, roles []*Role, options ...RequestOption) (st []*Role, err error) {
- body, err := s.RequestWithBucketID("PATCH", EndpointGuildRoles(guildID), roles, EndpointGuildRoles(guildID))
+ body, err := s.RequestWithBucketID("PATCH", EndpointGuildRoles(guildID), roles, EndpointGuildRoles(guildID), options...)
if err != nil {
return
}
@@ -1079,9 +1157,9 @@ func (s *Session) GuildRoleReorder(guildID string, roles []*Role) (st []*Role, e
// GuildRoleDelete deletes an existing role.
// guildID : The ID of a Guild.
// roleID : The ID of a Role.
-func (s *Session) GuildRoleDelete(guildID, roleID string) (err error) {
+func (s *Session) GuildRoleDelete(guildID, roleID string, options ...RequestOption) (err error) {
- _, err = s.RequestWithBucketID("DELETE", EndpointGuildRole(guildID, roleID), nil, EndpointGuildRole(guildID, ""))
+ _, err = s.RequestWithBucketID("DELETE", EndpointGuildRole(guildID, roleID), nil, EndpointGuildRole(guildID, ""), options...)
return
}
@@ -1090,7 +1168,7 @@ func (s *Session) GuildRoleDelete(guildID, roleID string) (err error) {
// Requires 'KICK_MEMBER' permission.
// guildID : The ID of a Guild.
// days : The number of days to count prune for (1 or more).
-func (s *Session) GuildPruneCount(guildID string, days uint32) (count uint32, err error) {
+func (s *Session) GuildPruneCount(guildID string, days uint32, options ...RequestOption) (count uint32, err error) {
count = 0
if days <= 0 {
@@ -1103,7 +1181,7 @@ func (s *Session) GuildPruneCount(guildID string, days uint32) (count uint32, er
}{}
uri := EndpointGuildPrune(guildID) + "?days=" + strconv.FormatUint(uint64(days), 10)
- body, err := s.RequestWithBucketID("GET", uri, nil, EndpointGuildPrune(guildID))
+ body, err := s.RequestWithBucketID("GET", uri, nil, EndpointGuildPrune(guildID), options...)
if err != nil {
return
}
@@ -1122,7 +1200,7 @@ func (s *Session) GuildPruneCount(guildID string, days uint32) (count uint32, er
// Returns an object with one 'pruned' key indicating the number of members that were removed in the prune operation.
// guildID : The ID of a Guild.
// days : The number of days to count prune for (1 or more).
-func (s *Session) GuildPrune(guildID string, days uint32) (count uint32, err error) {
+func (s *Session) GuildPrune(guildID string, days uint32, options ...RequestOption) (count uint32, err error) {
count = 0
@@ -1139,7 +1217,7 @@ func (s *Session) GuildPrune(guildID string, days uint32) (count uint32, err err
Pruned uint32 `json:"pruned"`
}{}
- body, err := s.RequestWithBucketID("POST", EndpointGuildPrune(guildID), data, EndpointGuildPrune(guildID))
+ body, err := s.RequestWithBucketID("POST", EndpointGuildPrune(guildID), data, EndpointGuildPrune(guildID), options...)
if err != nil {
return
}
@@ -1156,9 +1234,9 @@ func (s *Session) GuildPrune(guildID string, days uint32) (count uint32, err err
// GuildIntegrations returns an array of Integrations for a guild.
// guildID : The ID of a Guild.
-func (s *Session) GuildIntegrations(guildID string) (st []*Integration, err error) {
+func (s *Session) GuildIntegrations(guildID string, options ...RequestOption) (st []*Integration, err error) {
- body, err := s.RequestWithBucketID("GET", EndpointGuildIntegrations(guildID), nil, EndpointGuildIntegrations(guildID))
+ body, err := s.RequestWithBucketID("GET", EndpointGuildIntegrations(guildID), nil, EndpointGuildIntegrations(guildID), options...)
if err != nil {
return
}
@@ -1172,14 +1250,14 @@ func (s *Session) GuildIntegrations(guildID string) (st []*Integration, err erro
// guildID : The ID of a Guild.
// integrationType : The Integration type.
// integrationID : The ID of an integration.
-func (s *Session) GuildIntegrationCreate(guildID, integrationType, integrationID string) (err error) {
+func (s *Session) GuildIntegrationCreate(guildID, integrationType, integrationID string, options ...RequestOption) (err error) {
data := struct {
Type string `json:"type"`
ID string `json:"id"`
}{integrationType, integrationID}
- _, err = s.RequestWithBucketID("POST", EndpointGuildIntegrations(guildID), data, EndpointGuildIntegrations(guildID))
+ _, err = s.RequestWithBucketID("POST", EndpointGuildIntegrations(guildID), data, EndpointGuildIntegrations(guildID), options...)
return
}
@@ -1190,7 +1268,7 @@ func (s *Session) GuildIntegrationCreate(guildID, integrationType, integrationID
// expireBehavior : The behavior when an integration subscription lapses (see the integration object documentation).
// expireGracePeriod : Period (in seconds) where the integration will ignore lapsed subscriptions.
// enableEmoticons : Whether emoticons should be synced for this integration (twitch only currently).
-func (s *Session) GuildIntegrationEdit(guildID, integrationID string, expireBehavior, expireGracePeriod int, enableEmoticons bool) (err error) {
+func (s *Session) GuildIntegrationEdit(guildID, integrationID string, expireBehavior, expireGracePeriod int, enableEmoticons bool, options ...RequestOption) (err error) {
data := struct {
ExpireBehavior int `json:"expire_behavior"`
@@ -1198,23 +1276,23 @@ func (s *Session) GuildIntegrationEdit(guildID, integrationID string, expireBeha
EnableEmoticons bool `json:"enable_emoticons"`
}{expireBehavior, expireGracePeriod, enableEmoticons}
- _, err = s.RequestWithBucketID("PATCH", EndpointGuildIntegration(guildID, integrationID), data, EndpointGuildIntegration(guildID, ""))
+ _, err = s.RequestWithBucketID("PATCH", EndpointGuildIntegration(guildID, integrationID), data, EndpointGuildIntegration(guildID, ""), options...)
return
}
// GuildIntegrationDelete removes the given integration from the Guild.
// guildID : The ID of a Guild.
// integrationID : The ID of an integration.
-func (s *Session) GuildIntegrationDelete(guildID, integrationID string) (err error) {
+func (s *Session) GuildIntegrationDelete(guildID, integrationID string, options ...RequestOption) (err error) {
- _, err = s.RequestWithBucketID("DELETE", EndpointGuildIntegration(guildID, integrationID), nil, EndpointGuildIntegration(guildID, ""))
+ _, err = s.RequestWithBucketID("DELETE", EndpointGuildIntegration(guildID, integrationID), nil, EndpointGuildIntegration(guildID, ""), options...)
return
}
// GuildIcon returns an image.Image of a guild icon.
// guildID : The ID of a Guild.
-func (s *Session) GuildIcon(guildID string) (img image.Image, err error) {
- g, err := s.Guild(guildID)
+func (s *Session) GuildIcon(guildID string, options ...RequestOption) (img image.Image, err error) {
+ g, err := s.Guild(guildID, options...)
if err != nil {
return
}
@@ -1224,7 +1302,7 @@ func (s *Session) GuildIcon(guildID string) (img image.Image, err error) {
return
}
- body, err := s.RequestWithBucketID("GET", EndpointGuildIcon(guildID, g.Icon), nil, EndpointGuildIcon(guildID, ""))
+ body, err := s.RequestWithBucketID("GET", EndpointGuildIcon(guildID, g.Icon), nil, EndpointGuildIcon(guildID, ""), options...)
if err != nil {
return
}
@@ -1235,8 +1313,8 @@ func (s *Session) GuildIcon(guildID string) (img image.Image, err error) {
// GuildSplash returns an image.Image of a guild splash image.
// guildID : The ID of a Guild.
-func (s *Session) GuildSplash(guildID string) (img image.Image, err error) {
- g, err := s.Guild(guildID)
+func (s *Session) GuildSplash(guildID string, options ...RequestOption) (img image.Image, err error) {
+ g, err := s.Guild(guildID, options...)
if err != nil {
return
}
@@ -1246,7 +1324,7 @@ func (s *Session) GuildSplash(guildID string) (img image.Image, err error) {
return
}
- body, err := s.RequestWithBucketID("GET", EndpointGuildSplash(guildID, g.Splash), nil, EndpointGuildSplash(guildID, ""))
+ body, err := s.RequestWithBucketID("GET", EndpointGuildSplash(guildID, g.Splash), nil, EndpointGuildSplash(guildID, ""), options...)
if err != nil {
return
}
@@ -1257,9 +1335,9 @@ func (s *Session) GuildSplash(guildID string) (img image.Image, err error) {
// GuildEmbed returns the embed for a Guild.
// guildID : The ID of a Guild.
-func (s *Session) GuildEmbed(guildID string) (st *GuildEmbed, err error) {
+func (s *Session) GuildEmbed(guildID string, options ...RequestOption) (st *GuildEmbed, err error) {
- body, err := s.RequestWithBucketID("GET", EndpointGuildEmbed(guildID), nil, EndpointGuildEmbed(guildID))
+ body, err := s.RequestWithBucketID("GET", EndpointGuildEmbed(guildID), nil, EndpointGuildEmbed(guildID), options...)
if err != nil {
return
}
@@ -1271,8 +1349,8 @@ func (s *Session) GuildEmbed(guildID string) (st *GuildEmbed, err error) {
// GuildEmbedEdit edits the embed of a Guild.
// guildID : The ID of a Guild.
// data : New GuildEmbed data.
-func (s *Session) GuildEmbedEdit(guildID string, data *GuildEmbed) (err error) {
- _, err = s.RequestWithBucketID("PATCH", EndpointGuildEmbed(guildID), data, EndpointGuildEmbed(guildID))
+func (s *Session) GuildEmbedEdit(guildID string, data *GuildEmbed, options ...RequestOption) (err error) {
+ _, err = s.RequestWithBucketID("PATCH", EndpointGuildEmbed(guildID), data, EndpointGuildEmbed(guildID), options...)
return
}
@@ -1282,7 +1360,7 @@ func (s *Session) GuildEmbedEdit(guildID string, data *GuildEmbed) (err error) {
// beforeID : If provided all log entries returned will be before the given ID.
// actionType : If provided the log will be filtered for the given Action Type.
// limit : The number messages that can be returned. (default 50, min 1, max 100)
-func (s *Session) GuildAuditLog(guildID, userID, beforeID string, actionType, limit int) (st *GuildAuditLog, err error) {
+func (s *Session) GuildAuditLog(guildID, userID, beforeID string, actionType, limit int, options ...RequestOption) (st *GuildAuditLog, err error) {
uri := EndpointGuildAuditLogs(guildID)
@@ -1303,7 +1381,7 @@ func (s *Session) GuildAuditLog(guildID, userID, beforeID string, actionType, li
uri = fmt.Sprintf("%s?%s", uri, v.Encode())
}
- body, err := s.RequestWithBucketID("GET", uri, nil, EndpointGuildAuditLogs(guildID))
+ body, err := s.RequestWithBucketID("GET", uri, nil, EndpointGuildAuditLogs(guildID), options...)
if err != nil {
return
}
@@ -1314,9 +1392,9 @@ func (s *Session) GuildAuditLog(guildID, userID, beforeID string, actionType, li
// GuildEmojis returns all emoji
// guildID : The ID of a Guild.
-func (s *Session) GuildEmojis(guildID string) (emoji []*Emoji, err error) {
+func (s *Session) GuildEmojis(guildID string, options ...RequestOption) (emoji []*Emoji, err error) {
- body, err := s.RequestWithBucketID("GET", EndpointGuildEmojis(guildID), nil, EndpointGuildEmojis(guildID))
+ body, err := s.RequestWithBucketID("GET", EndpointGuildEmojis(guildID), nil, EndpointGuildEmojis(guildID), options...)
if err != nil {
return
}
@@ -1328,9 +1406,9 @@ func (s *Session) GuildEmojis(guildID string) (emoji []*Emoji, err error) {
// GuildEmoji returns specified emoji.
// guildID : The ID of a Guild
// emojiID : The ID of an Emoji to retrieve
-func (s *Session) GuildEmoji(guildID, emojiID string) (emoji *Emoji, err error) {
+func (s *Session) GuildEmoji(guildID, emojiID string, options ...RequestOption) (emoji *Emoji, err error) {
var body []byte
- body, err = s.RequestWithBucketID("GET", EndpointGuildEmoji(guildID, emojiID), nil, EndpointGuildEmoji(guildID, emojiID))
+ body, err = s.RequestWithBucketID("GET", EndpointGuildEmoji(guildID, emojiID), nil, EndpointGuildEmoji(guildID, emojiID), options...)
if err != nil {
return
}
@@ -1342,8 +1420,8 @@ func (s *Session) GuildEmoji(guildID, emojiID string) (emoji *Emoji, err error)
// GuildEmojiCreate creates a new Emoji.
// guildID : The ID of a Guild.
// data : New Emoji data.
-func (s *Session) GuildEmojiCreate(guildID string, data *EmojiParams) (emoji *Emoji, err error) {
- body, err := s.RequestWithBucketID("POST", EndpointGuildEmojis(guildID), data, EndpointGuildEmojis(guildID))
+func (s *Session) GuildEmojiCreate(guildID string, data *EmojiParams, options ...RequestOption) (emoji *Emoji, err error) {
+ body, err := s.RequestWithBucketID("POST", EndpointGuildEmojis(guildID), data, EndpointGuildEmojis(guildID), options...)
if err != nil {
return
}
@@ -1356,8 +1434,8 @@ func (s *Session) GuildEmojiCreate(guildID string, data *EmojiParams) (emoji *Em
// guildID : The ID of a Guild.
// emojiID : The ID of an Emoji.
// data : Updated Emoji data.
-func (s *Session) GuildEmojiEdit(guildID, emojiID string, data *EmojiParams) (emoji *Emoji, err error) {
- body, err := s.RequestWithBucketID("PATCH", EndpointGuildEmoji(guildID, emojiID), data, EndpointGuildEmojis(guildID))
+func (s *Session) GuildEmojiEdit(guildID, emojiID string, data *EmojiParams, options ...RequestOption) (emoji *Emoji, err error) {
+ body, err := s.RequestWithBucketID("PATCH", EndpointGuildEmoji(guildID, emojiID), data, EndpointGuildEmojis(guildID), options...)
if err != nil {
return
}
@@ -1369,17 +1447,17 @@ func (s *Session) GuildEmojiEdit(guildID, emojiID string, data *EmojiParams) (em
// GuildEmojiDelete deletes an Emoji.
// guildID : The ID of a Guild.
// emojiID : The ID of an Emoji.
-func (s *Session) GuildEmojiDelete(guildID, emojiID string) (err error) {
+func (s *Session) GuildEmojiDelete(guildID, emojiID string, options ...RequestOption) (err error) {
- _, err = s.RequestWithBucketID("DELETE", EndpointGuildEmoji(guildID, emojiID), nil, EndpointGuildEmojis(guildID))
+ _, err = s.RequestWithBucketID("DELETE", EndpointGuildEmoji(guildID, emojiID), nil, EndpointGuildEmojis(guildID), options...)
return
}
// GuildTemplate returns a GuildTemplate for the given code
// templateCode: The Code of a GuildTemplate
-func (s *Session) GuildTemplate(templateCode string) (st *GuildTemplate, err error) {
+func (s *Session) GuildTemplate(templateCode string, options ...RequestOption) (st *GuildTemplate, err error) {
- body, err := s.RequestWithBucketID("GET", EndpointGuildTemplate(templateCode), nil, EndpointGuildTemplate(templateCode))
+ body, err := s.RequestWithBucketID("GET", EndpointGuildTemplate(templateCode), nil, EndpointGuildTemplate(templateCode), options...)
if err != nil {
return
}
@@ -1392,14 +1470,14 @@ func (s *Session) GuildTemplate(templateCode string) (st *GuildTemplate, err err
// templateCode: The Code of a GuildTemplate
// name: The name of the guild (2-100) characters
// icon: base64 encoded 128x128 image for the guild icon
-func (s *Session) GuildCreateWithTemplate(templateCode, name, icon string) (st *Guild, err error) {
+func (s *Session) GuildCreateWithTemplate(templateCode, name, icon string, options ...RequestOption) (st *Guild, err error) {
data := struct {
Name string `json:"name"`
Icon string `json:"icon"`
}{name, icon}
- body, err := s.RequestWithBucketID("POST", EndpointGuildTemplate(templateCode), data, EndpointGuildTemplate(templateCode))
+ body, err := s.RequestWithBucketID("POST", EndpointGuildTemplate(templateCode), data, EndpointGuildTemplate(templateCode), options...)
if err != nil {
return
}
@@ -1410,9 +1488,9 @@ func (s *Session) GuildCreateWithTemplate(templateCode, name, icon string) (st *
// GuildTemplates returns all of GuildTemplates
// guildID: The ID of the guild
-func (s *Session) GuildTemplates(guildID string) (st []*GuildTemplate, err error) {
+func (s *Session) GuildTemplates(guildID string, options ...RequestOption) (st []*GuildTemplate, err error) {
- body, err := s.RequestWithBucketID("GET", EndpointGuildTemplates(guildID), nil, EndpointGuildTemplates(guildID))
+ body, err := s.RequestWithBucketID("GET", EndpointGuildTemplates(guildID), nil, EndpointGuildTemplates(guildID), options...)
if err != nil {
return
}
@@ -1424,8 +1502,8 @@ func (s *Session) GuildTemplates(guildID string) (st []*GuildTemplate, err error
// GuildTemplateCreate creates a template for the guild
// guildID : The ID of the guild
// data : Template metadata
-func (s *Session) GuildTemplateCreate(guildID string, data *GuildTemplateParams) (st *GuildTemplate) {
- body, err := s.RequestWithBucketID("POST", EndpointGuildTemplates(guildID), data, EndpointGuildTemplates(guildID))
+func (s *Session) GuildTemplateCreate(guildID string, data *GuildTemplateParams, options ...RequestOption) (st *GuildTemplate) {
+ body, err := s.RequestWithBucketID("POST", EndpointGuildTemplates(guildID), data, EndpointGuildTemplates(guildID), options...)
if err != nil {
return
}
@@ -1437,9 +1515,9 @@ func (s *Session) GuildTemplateCreate(guildID string, data *GuildTemplateParams)
// GuildTemplateSync syncs the template to the guild's current state
// guildID: The ID of the guild
// templateCode: The code of the template
-func (s *Session) GuildTemplateSync(guildID, templateCode string) (err error) {
+func (s *Session) GuildTemplateSync(guildID, templateCode string, options ...RequestOption) (err error) {
- _, err = s.RequestWithBucketID("PUT", EndpointGuildTemplateSync(guildID, templateCode), nil, EndpointGuildTemplateSync(guildID, ""))
+ _, err = s.RequestWithBucketID("PUT", EndpointGuildTemplateSync(guildID, templateCode), nil, EndpointGuildTemplateSync(guildID, ""), options...)
return
}
@@ -1447,9 +1525,9 @@ func (s *Session) GuildTemplateSync(guildID, templateCode string) (err error) {
// guildID : The ID of the guild
// templateCode : The code of the template
// data : New template metadata
-func (s *Session) GuildTemplateEdit(guildID, templateCode string, data *GuildTemplateParams) (st *GuildTemplate, err error) {
+func (s *Session) GuildTemplateEdit(guildID, templateCode string, data *GuildTemplateParams, options ...RequestOption) (st *GuildTemplate, err error) {
- body, err := s.RequestWithBucketID("PATCH", EndpointGuildTemplateSync(guildID, templateCode), data, EndpointGuildTemplateSync(guildID, ""))
+ body, err := s.RequestWithBucketID("PATCH", EndpointGuildTemplateSync(guildID, templateCode), data, EndpointGuildTemplateSync(guildID, ""), options...)
if err != nil {
return
}
@@ -1461,9 +1539,9 @@ func (s *Session) GuildTemplateEdit(guildID, templateCode string, data *GuildTem
// GuildTemplateDelete deletes the template
// guildID: The ID of the guild
// templateCode: The code of the template
-func (s *Session) GuildTemplateDelete(guildID, templateCode string) (err error) {
+func (s *Session) GuildTemplateDelete(guildID, templateCode string, options ...RequestOption) (err error) {
- _, err = s.RequestWithBucketID("DELETE", EndpointGuildTemplateSync(guildID, templateCode), nil, EndpointGuildTemplateSync(guildID, ""))
+ _, err = s.RequestWithBucketID("DELETE", EndpointGuildTemplateSync(guildID, templateCode), nil, EndpointGuildTemplateSync(guildID, ""), options...)
return
}
@@ -1473,8 +1551,8 @@ func (s *Session) GuildTemplateDelete(guildID, templateCode string) (err error)
// Channel returns a Channel structure of a specific Channel.
// channelID : The ID of the Channel you want returned.
-func (s *Session) Channel(channelID string) (st *Channel, err error) {
- body, err := s.RequestWithBucketID("GET", EndpointChannel(channelID), nil, EndpointChannel(channelID))
+func (s *Session) Channel(channelID string, options ...RequestOption) (st *Channel, err error) {
+ body, err := s.RequestWithBucketID("GET", EndpointChannel(channelID), nil, EndpointChannel(channelID), options...)
if err != nil {
return
}
@@ -1486,8 +1564,8 @@ func (s *Session) Channel(channelID string) (st *Channel, err error) {
// ChannelEdit edits the given channel and returns the updated Channel data.
// channelID : The ID of a Channel.
// data : New Channel data.
-func (s *Session) ChannelEdit(channelID string, data *ChannelEdit) (st *Channel, err error) {
- body, err := s.RequestWithBucketID("PATCH", EndpointChannel(channelID), data, EndpointChannel(channelID))
+func (s *Session) ChannelEdit(channelID string, data *ChannelEdit, options ...RequestOption) (st *Channel, err error) {
+ body, err := s.RequestWithBucketID("PATCH", EndpointChannel(channelID), data, EndpointChannel(channelID), options...)
if err != nil {
return
}
@@ -1501,15 +1579,15 @@ func (s *Session) ChannelEdit(channelID string, data *ChannelEdit) (st *Channel,
// NOTE: deprecated, use ChannelEdit instead
// channelID : The ID of a Channel
// data : The channel struct to send
-func (s *Session) ChannelEditComplex(channelID string, data *ChannelEdit) (st *Channel, err error) {
- return s.ChannelEdit(channelID, data)
+func (s *Session) ChannelEditComplex(channelID string, data *ChannelEdit, options ...RequestOption) (st *Channel, err error) {
+ return s.ChannelEdit(channelID, data, options...)
}
// ChannelDelete deletes the given channel
// channelID : The ID of a Channel
-func (s *Session) ChannelDelete(channelID string) (st *Channel, err error) {
+func (s *Session) ChannelDelete(channelID string, options ...RequestOption) (st *Channel, err error) {
- body, err := s.RequestWithBucketID("DELETE", EndpointChannel(channelID), nil, EndpointChannel(channelID))
+ body, err := s.RequestWithBucketID("DELETE", EndpointChannel(channelID), nil, EndpointChannel(channelID), options...)
if err != nil {
return
}
@@ -1521,9 +1599,9 @@ func (s *Session) ChannelDelete(channelID string) (st *Channel, err error) {
// ChannelTyping broadcasts to all members that authenticated user is typing in
// the given channel.
// channelID : The ID of a Channel
-func (s *Session) ChannelTyping(channelID string) (err error) {
+func (s *Session) ChannelTyping(channelID string, options ...RequestOption) (err error) {
- _, err = s.RequestWithBucketID("POST", EndpointChannelTyping(channelID), nil, EndpointChannelTyping(channelID))
+ _, err = s.RequestWithBucketID("POST", EndpointChannelTyping(channelID), nil, EndpointChannelTyping(channelID), options...)
return
}
@@ -1534,7 +1612,7 @@ func (s *Session) ChannelTyping(channelID string) (err error) {
// beforeID : If provided all messages returned will be before given ID.
// afterID : If provided all messages returned will be after given ID.
// aroundID : If provided all messages returned will be around given ID.
-func (s *Session) ChannelMessages(channelID string, limit int, beforeID, afterID, aroundID string) (st []*Message, err error) {
+func (s *Session) ChannelMessages(channelID string, limit int, beforeID, afterID, aroundID string, options ...RequestOption) (st []*Message, err error) {
uri := EndpointChannelMessages(channelID)
@@ -1555,7 +1633,7 @@ func (s *Session) ChannelMessages(channelID string, limit int, beforeID, afterID
uri += "?" + v.Encode()
}
- body, err := s.RequestWithBucketID("GET", uri, nil, EndpointChannelMessages(channelID))
+ body, err := s.RequestWithBucketID("GET", uri, nil, EndpointChannelMessages(channelID), options...)
if err != nil {
return
}
@@ -1567,9 +1645,9 @@ func (s *Session) ChannelMessages(channelID string, limit int, beforeID, afterID
// ChannelMessage gets a single message by ID from a given channel.
// channeld : The ID of a Channel
// messageID : the ID of a Message
-func (s *Session) ChannelMessage(channelID, messageID string) (st *Message, err error) {
+func (s *Session) ChannelMessage(channelID, messageID string, options ...RequestOption) (st *Message, err error) {
- response, err := s.RequestWithBucketID("GET", EndpointChannelMessage(channelID, messageID), nil, EndpointChannelMessage(channelID, ""))
+ response, err := s.RequestWithBucketID("GET", EndpointChannelMessage(channelID, messageID), nil, EndpointChannelMessage(channelID, ""), options...)
if err != nil {
return
}
@@ -1581,10 +1659,10 @@ func (s *Session) ChannelMessage(channelID, messageID string) (st *Message, err
// ChannelMessageSend sends a message to the given channel.
// channelID : The ID of a Channel.
// content : The message to send.
-func (s *Session) ChannelMessageSend(channelID string, content string) (*Message, error) {
+func (s *Session) ChannelMessageSend(channelID string, content string, options ...RequestOption) (*Message, error) {
return s.ChannelMessageSendComplex(channelID, &MessageSend{
Content: content,
- })
+ }, options...)
}
var quoteEscaper = strings.NewReplacer("\\", "\\\\", `"`, "\\\"")
@@ -1592,7 +1670,7 @@ var quoteEscaper = strings.NewReplacer("\\", "\\\\", `"`, "\\\"")
// ChannelMessageSendComplex sends a message to the given channel.
// channelID : The ID of a Channel.
// data : The message struct to send.
-func (s *Session) ChannelMessageSendComplex(channelID string, data *MessageSend) (st *Message, err error) {
+func (s *Session) ChannelMessageSendComplex(channelID string, data *MessageSend, options ...RequestOption) (st *Message, err error) {
// TODO: Remove this when compatibility is not required.
if data.Embed != nil {
if data.Embeds == nil {
@@ -1628,9 +1706,9 @@ func (s *Session) ChannelMessageSendComplex(channelID string, data *MessageSend)
return st, encodeErr
}
- response, err = s.request("POST", endpoint, contentType, body, endpoint, 0)
+ response, err = s.request("POST", endpoint, contentType, body, endpoint, 0, options...)
} else {
- response, err = s.RequestWithBucketID("POST", endpoint, data, endpoint)
+ response, err = s.RequestWithBucketID("POST", endpoint, data, endpoint, options...)
}
if err != nil {
return
@@ -1643,63 +1721,63 @@ func (s *Session) ChannelMessageSendComplex(channelID string, data *MessageSend)
// ChannelMessageSendTTS sends a message to the given channel with Text to Speech.
// channelID : The ID of a Channel.
// content : The message to send.
-func (s *Session) ChannelMessageSendTTS(channelID string, content string) (*Message, error) {
+func (s *Session) ChannelMessageSendTTS(channelID string, content string, options ...RequestOption) (*Message, error) {
return s.ChannelMessageSendComplex(channelID, &MessageSend{
Content: content,
TTS: true,
- })
+ }, options...)
}
// ChannelMessageSendEmbed sends a message to the given channel with embedded data.
// channelID : The ID of a Channel.
// embed : The embed data to send.
-func (s *Session) ChannelMessageSendEmbed(channelID string, embed *MessageEmbed) (*Message, error) {
- return s.ChannelMessageSendEmbeds(channelID, []*MessageEmbed{embed})
+func (s *Session) ChannelMessageSendEmbed(channelID string, embed *MessageEmbed, options ...RequestOption) (*Message, error) {
+ return s.ChannelMessageSendEmbeds(channelID, []*MessageEmbed{embed}, options...)
}
// ChannelMessageSendEmbeds sends a message to the given channel with multiple embedded data.
// channelID : The ID of a Channel.
// embeds : The embeds data to send.
-func (s *Session) ChannelMessageSendEmbeds(channelID string, embeds []*MessageEmbed) (*Message, error) {
+func (s *Session) ChannelMessageSendEmbeds(channelID string, embeds []*MessageEmbed, options ...RequestOption) (*Message, error) {
return s.ChannelMessageSendComplex(channelID, &MessageSend{
Embeds: embeds,
- })
+ }, options...)
}
// ChannelMessageSendReply sends a message to the given channel with reference data.
// channelID : The ID of a Channel.
// content : The message to send.
// reference : The message reference to send.
-func (s *Session) ChannelMessageSendReply(channelID string, content string, reference *MessageReference) (*Message, error) {
+func (s *Session) ChannelMessageSendReply(channelID string, content string, reference *MessageReference, options ...RequestOption) (*Message, error) {
if reference == nil {
return nil, fmt.Errorf("reply attempted with nil message reference")
}
return s.ChannelMessageSendComplex(channelID, &MessageSend{
Content: content,
Reference: reference,
- })
+ }, options...)
}
// ChannelMessageSendEmbedReply sends a message to the given channel with reference data and embedded data.
// channelID : The ID of a Channel.
// embed : The embed data to send.
// reference : The message reference to send.
-func (s *Session) ChannelMessageSendEmbedReply(channelID string, embed *MessageEmbed, reference *MessageReference) (*Message, error) {
- return s.ChannelMessageSendEmbedsReply(channelID, []*MessageEmbed{embed}, reference)
+func (s *Session) ChannelMessageSendEmbedReply(channelID string, embed *MessageEmbed, reference *MessageReference, options ...RequestOption) (*Message, error) {
+ return s.ChannelMessageSendEmbedsReply(channelID, []*MessageEmbed{embed}, reference, options...)
}
// ChannelMessageSendEmbedsReply sends a message to the given channel with reference data and multiple embedded data.
// channelID : The ID of a Channel.
// embeds : The embeds data to send.
// reference : The message reference to send.
-func (s *Session) ChannelMessageSendEmbedsReply(channelID string, embeds []*MessageEmbed, reference *MessageReference) (*Message, error) {
+func (s *Session) ChannelMessageSendEmbedsReply(channelID string, embeds []*MessageEmbed, reference *MessageReference, options ...RequestOption) (*Message, error) {
if reference == nil {
return nil, fmt.Errorf("reply attempted with nil message reference")
}
return s.ChannelMessageSendComplex(channelID, &MessageSend{
Embeds: embeds,
Reference: reference,
- })
+ }, options...)
}
// ChannelMessageEdit edits an existing message, replacing it entirely with
@@ -1707,13 +1785,13 @@ func (s *Session) ChannelMessageSendEmbedsReply(channelID string, embeds []*Mess
// channelID : The ID of a Channel
// messageID : The ID of a Message
// content : The contents of the message
-func (s *Session) ChannelMessageEdit(channelID, messageID, content string) (*Message, error) {
- return s.ChannelMessageEditComplex(NewMessageEdit(channelID, messageID).SetContent(content))
+func (s *Session) ChannelMessageEdit(channelID, messageID, content string, options ...RequestOption) (*Message, error) {
+ return s.ChannelMessageEditComplex(NewMessageEdit(channelID, messageID).SetContent(content), options...)
}
// ChannelMessageEditComplex edits an existing message, replacing it entirely with
// the given MessageEdit struct
-func (s *Session) ChannelMessageEditComplex(m *MessageEdit) (st *Message, err error) {
+func (s *Session) ChannelMessageEditComplex(m *MessageEdit, options ...RequestOption) (st *Message, err error) {
// TODO: Remove this when compatibility is not required.
if m.Embed != nil {
if m.Embeds == nil {
@@ -1729,7 +1807,19 @@ func (s *Session) ChannelMessageEditComplex(m *MessageEdit) (st *Message, err er
embed.Type = "rich"
}
}
- response, err := s.RequestWithBucketID("PATCH", EndpointChannelMessage(m.Channel, m.ID), m, EndpointChannelMessage(m.Channel, ""))
+
+ endpoint := EndpointChannelMessage(m.Channel, m.ID)
+
+ var response []byte
+ if len(m.Files) > 0 {
+ contentType, body, encodeErr := MultipartBodyWithJSON(m, m.Files)
+ if encodeErr != nil {
+ return st, encodeErr
+ }
+ response, err = s.request("PATCH", endpoint, contentType, body, EndpointChannelMessage(m.Channel, ""), 0, options...)
+ } else {
+ response, err = s.RequestWithBucketID("PATCH", endpoint, m, EndpointChannelMessage(m.Channel, ""), options...)
+ }
if err != nil {
return
}
@@ -1742,22 +1832,22 @@ func (s *Session) ChannelMessageEditComplex(m *MessageEdit) (st *Message, err er
// channelID : The ID of a Channel
// messageID : The ID of a Message
// embed : The embed data to send
-func (s *Session) ChannelMessageEditEmbed(channelID, messageID string, embed *MessageEmbed) (*Message, error) {
- return s.ChannelMessageEditEmbeds(channelID, messageID, []*MessageEmbed{embed})
+func (s *Session) ChannelMessageEditEmbed(channelID, messageID string, embed *MessageEmbed, options ...RequestOption) (*Message, error) {
+ return s.ChannelMessageEditEmbeds(channelID, messageID, []*MessageEmbed{embed}, options...)
}
// ChannelMessageEditEmbeds edits an existing message with multiple embedded data.
// channelID : The ID of a Channel
// messageID : The ID of a Message
// embeds : The embeds data to send
-func (s *Session) ChannelMessageEditEmbeds(channelID, messageID string, embeds []*MessageEmbed) (*Message, error) {
- return s.ChannelMessageEditComplex(NewMessageEdit(channelID, messageID).SetEmbeds(embeds))
+func (s *Session) ChannelMessageEditEmbeds(channelID, messageID string, embeds []*MessageEmbed, options ...RequestOption) (*Message, error) {
+ return s.ChannelMessageEditComplex(NewMessageEdit(channelID, messageID).SetEmbeds(embeds), options...)
}
// ChannelMessageDelete deletes a message from the Channel.
-func (s *Session) ChannelMessageDelete(channelID, messageID string) (err error) {
+func (s *Session) ChannelMessageDelete(channelID, messageID string, options ...RequestOption) (err error) {
- _, err = s.RequestWithBucketID("DELETE", EndpointChannelMessage(channelID, messageID), nil, EndpointChannelMessage(channelID, ""))
+ _, err = s.RequestWithBucketID("DELETE", EndpointChannelMessage(channelID, messageID), nil, EndpointChannelMessage(channelID, ""), options...)
return
}
@@ -1766,14 +1856,14 @@ func (s *Session) ChannelMessageDelete(channelID, messageID string) (err error)
// If the slice is empty do nothing.
// channelID : The ID of the channel for the messages to delete.
// messages : The IDs of the messages to be deleted. A slice of string IDs. A maximum of 100 messages.
-func (s *Session) ChannelMessagesBulkDelete(channelID string, messages []string) (err error) {
+func (s *Session) ChannelMessagesBulkDelete(channelID string, messages []string, options ...RequestOption) (err error) {
if len(messages) == 0 {
return
}
if len(messages) == 1 {
- err = s.ChannelMessageDelete(channelID, messages[0])
+ err = s.ChannelMessageDelete(channelID, messages[0], options...)
return
}
@@ -1785,34 +1875,34 @@ func (s *Session) ChannelMessagesBulkDelete(channelID string, messages []string)
Messages []string `json:"messages"`
}{messages}
- _, err = s.RequestWithBucketID("POST", EndpointChannelMessagesBulkDelete(channelID), data, EndpointChannelMessagesBulkDelete(channelID))
+ _, err = s.RequestWithBucketID("POST", EndpointChannelMessagesBulkDelete(channelID), data, EndpointChannelMessagesBulkDelete(channelID), options...)
return
}
// ChannelMessagePin pins a message within a given channel.
// channelID: The ID of a channel.
// messageID: The ID of a message.
-func (s *Session) ChannelMessagePin(channelID, messageID string) (err error) {
+func (s *Session) ChannelMessagePin(channelID, messageID string, options ...RequestOption) (err error) {
- _, err = s.RequestWithBucketID("PUT", EndpointChannelMessagePin(channelID, messageID), nil, EndpointChannelMessagePin(channelID, ""))
+ _, err = s.RequestWithBucketID("PUT", EndpointChannelMessagePin(channelID, messageID), nil, EndpointChannelMessagePin(channelID, ""), options...)
return
}
// ChannelMessageUnpin unpins a message within a given channel.
// channelID: The ID of a channel.
// messageID: The ID of a message.
-func (s *Session) ChannelMessageUnpin(channelID, messageID string) (err error) {
+func (s *Session) ChannelMessageUnpin(channelID, messageID string, options ...RequestOption) (err error) {
- _, err = s.RequestWithBucketID("DELETE", EndpointChannelMessagePin(channelID, messageID), nil, EndpointChannelMessagePin(channelID, ""))
+ _, err = s.RequestWithBucketID("DELETE", EndpointChannelMessagePin(channelID, messageID), nil, EndpointChannelMessagePin(channelID, ""), options...)
return
}
// ChannelMessagesPinned returns an array of Message structures for pinned messages
// within a given channel
// channelID : The ID of a Channel.
-func (s *Session) ChannelMessagesPinned(channelID string) (st []*Message, err error) {
+func (s *Session) ChannelMessagesPinned(channelID string, options ...RequestOption) (st []*Message, err error) {
- body, err := s.RequestWithBucketID("GET", EndpointChannelMessagesPins(channelID), nil, EndpointChannelMessagesPins(channelID))
+ body, err := s.RequestWithBucketID("GET", EndpointChannelMessagesPins(channelID), nil, EndpointChannelMessagesPins(channelID), options...)
if err != nil {
return
@@ -1826,8 +1916,8 @@ func (s *Session) ChannelMessagesPinned(channelID string) (st []*Message, err er
// channelID : The ID of a Channel.
// name: The name of the file.
// io.Reader : A reader for the file contents.
-func (s *Session) ChannelFileSend(channelID, name string, r io.Reader) (*Message, error) {
- return s.ChannelMessageSendComplex(channelID, &MessageSend{File: &File{Name: name, Reader: r}})
+func (s *Session) ChannelFileSend(channelID, name string, r io.Reader, options ...RequestOption) (*Message, error) {
+ return s.ChannelMessageSendComplex(channelID, &MessageSend{File: &File{Name: name, Reader: r}}, options...)
}
// ChannelFileSendWithMessage sends a file to the given channel with an message.
@@ -1836,15 +1926,15 @@ func (s *Session) ChannelFileSend(channelID, name string, r io.Reader) (*Message
// content: Optional Message content.
// name: The name of the file.
// io.Reader : A reader for the file contents.
-func (s *Session) ChannelFileSendWithMessage(channelID, content string, name string, r io.Reader) (*Message, error) {
- return s.ChannelMessageSendComplex(channelID, &MessageSend{File: &File{Name: name, Reader: r}, Content: content})
+func (s *Session) ChannelFileSendWithMessage(channelID, content string, name string, r io.Reader, options ...RequestOption) (*Message, error) {
+ return s.ChannelMessageSendComplex(channelID, &MessageSend{File: &File{Name: name, Reader: r}, Content: content}, options...)
}
// ChannelInvites returns an array of Invite structures for the given channel
// channelID : The ID of a Channel
-func (s *Session) ChannelInvites(channelID string) (st []*Invite, err error) {
+func (s *Session) ChannelInvites(channelID string, options ...RequestOption) (st []*Invite, err error) {
- body, err := s.RequestWithBucketID("GET", EndpointChannelInvites(channelID), nil, EndpointChannelInvites(channelID))
+ body, err := s.RequestWithBucketID("GET", EndpointChannelInvites(channelID), nil, EndpointChannelInvites(channelID), options...)
if err != nil {
return
}
@@ -1856,7 +1946,7 @@ func (s *Session) ChannelInvites(channelID string) (st []*Invite, err error) {
// ChannelInviteCreate creates a new invite for the given channel.
// channelID : The ID of a Channel
// i : An Invite struct with the values MaxAge, MaxUses and Temporary defined.
-func (s *Session) ChannelInviteCreate(channelID string, i Invite) (st *Invite, err error) {
+func (s *Session) ChannelInviteCreate(channelID string, i Invite, options ...RequestOption) (st *Invite, err error) {
data := struct {
MaxAge int `json:"max_age"`
@@ -1865,7 +1955,7 @@ func (s *Session) ChannelInviteCreate(channelID string, i Invite) (st *Invite, e
Unique bool `json:"unique"`
}{i.MaxAge, i.MaxUses, i.Temporary, i.Unique}
- body, err := s.RequestWithBucketID("POST", EndpointChannelInvites(channelID), data, EndpointChannelInvites(channelID))
+ body, err := s.RequestWithBucketID("POST", EndpointChannelInvites(channelID), data, EndpointChannelInvites(channelID), options...)
if err != nil {
return
}
@@ -1877,7 +1967,7 @@ func (s *Session) ChannelInviteCreate(channelID string, i Invite) (st *Invite, e
// ChannelPermissionSet creates a Permission Override for the given channel.
// NOTE: This func name may changed. Using Set instead of Create because
// you can both create a new override or update an override with this function.
-func (s *Session) ChannelPermissionSet(channelID, targetID string, targetType PermissionOverwriteType, allow, deny int64) (err error) {
+func (s *Session) ChannelPermissionSet(channelID, targetID string, targetType PermissionOverwriteType, allow, deny int64, options ...RequestOption) (err error) {
data := struct {
ID string `json:"id"`
@@ -1886,15 +1976,15 @@ func (s *Session) ChannelPermissionSet(channelID, targetID string, targetType Pe
Deny int64 `json:"deny,string"`
}{targetID, targetType, allow, deny}
- _, err = s.RequestWithBucketID("PUT", EndpointChannelPermission(channelID, targetID), data, EndpointChannelPermission(channelID, ""))
+ _, err = s.RequestWithBucketID("PUT", EndpointChannelPermission(channelID, targetID), data, EndpointChannelPermission(channelID, ""), options...)
return
}
// ChannelPermissionDelete deletes a specific permission override for the given channel.
// NOTE: Name of this func may change.
-func (s *Session) ChannelPermissionDelete(channelID, targetID string) (err error) {
+func (s *Session) ChannelPermissionDelete(channelID, targetID string, options ...RequestOption) (err error) {
- _, err = s.RequestWithBucketID("DELETE", EndpointChannelPermission(channelID, targetID), nil, EndpointChannelPermission(channelID, ""))
+ _, err = s.RequestWithBucketID("DELETE", EndpointChannelPermission(channelID, targetID), nil, EndpointChannelPermission(channelID, ""), options...)
return
}
@@ -1902,11 +1992,11 @@ func (s *Session) ChannelPermissionDelete(channelID, targetID string) (err error
// of the channel
// channelID : The ID of a Channel
// messageID : The ID of a Message
-func (s *Session) ChannelMessageCrosspost(channelID, messageID string) (st *Message, err error) {
+func (s *Session) ChannelMessageCrosspost(channelID, messageID string, options ...RequestOption) (st *Message, err error) {
endpoint := EndpointChannelMessageCrosspost(channelID, messageID)
- body, err := s.RequestWithBucketID("POST", endpoint, nil, endpoint)
+ body, err := s.RequestWithBucketID("POST", endpoint, nil, endpoint, options...)
if err != nil {
return
}
@@ -1918,7 +2008,7 @@ func (s *Session) ChannelMessageCrosspost(channelID, messageID string) (st *Mess
// ChannelNewsFollow follows a news channel in the targetID
// channelID : The ID of a News Channel
// targetID : The ID of a Channel where the News Channel should post to
-func (s *Session) ChannelNewsFollow(channelID, targetID string) (st *ChannelFollow, err error) {
+func (s *Session) ChannelNewsFollow(channelID, targetID string, options ...RequestOption) (st *ChannelFollow, err error) {
endpoint := EndpointChannelFollow(channelID)
@@ -1926,7 +2016,7 @@ func (s *Session) ChannelNewsFollow(channelID, targetID string) (st *ChannelFoll
WebhookChannelID string `json:"webhook_channel_id"`
}{targetID}
- body, err := s.RequestWithBucketID("POST", endpoint, data, endpoint)
+ body, err := s.RequestWithBucketID("POST", endpoint, data, endpoint, options...)
if err != nil {
return
}
@@ -1941,9 +2031,9 @@ func (s *Session) ChannelNewsFollow(channelID, targetID string) (st *ChannelFoll
// Invite returns an Invite structure of the given invite
// inviteID : The invite code
-func (s *Session) Invite(inviteID string) (st *Invite, err error) {
+func (s *Session) Invite(inviteID string, options ...RequestOption) (st *Invite, err error) {
- body, err := s.RequestWithBucketID("GET", EndpointInvite(inviteID), nil, EndpointInvite(""))
+ body, err := s.RequestWithBucketID("GET", EndpointInvite(inviteID), nil, EndpointInvite(""), options...)
if err != nil {
return
}
@@ -1954,9 +2044,9 @@ func (s *Session) Invite(inviteID string) (st *Invite, err error) {
// InviteWithCounts returns an Invite structure of the given invite including approximate member counts
// inviteID : The invite code
-func (s *Session) InviteWithCounts(inviteID string) (st *Invite, err error) {
+func (s *Session) InviteWithCounts(inviteID string, options ...RequestOption) (st *Invite, err error) {
- body, err := s.RequestWithBucketID("GET", EndpointInvite(inviteID)+"?with_counts=true", nil, EndpointInvite(""))
+ body, err := s.RequestWithBucketID("GET", EndpointInvite(inviteID)+"?with_counts=true", nil, EndpointInvite(""), options...)
if err != nil {
return
}
@@ -1966,11 +2056,11 @@ func (s *Session) InviteWithCounts(inviteID string) (st *Invite, err error) {
}
// InviteComplex returns an Invite structure of the given invite including specified fields.
-// inviteID : The invite code
-// guildScheduledEventID : If specified, includes specified guild scheduled event.
-// withCounts : Whether to include approximate member counts or not
-// withExpiration : Whether to include expiration time or not
-func (s *Session) InviteComplex(inviteID, guildScheduledEventID string, withCounts, withExpiration bool) (st *Invite, err error) {
+// inviteID : The invite code
+// guildScheduledEventID : If specified, includes specified guild scheduled event.
+// withCounts : Whether to include approximate member counts or not
+// withExpiration : Whether to include expiration time or not
+func (s *Session) InviteComplex(inviteID, guildScheduledEventID string, withCounts, withExpiration bool, options ...RequestOption) (st *Invite, err error) {
endpoint := EndpointInvite(inviteID)
v := url.Values{}
if guildScheduledEventID != "" {
@@ -1987,7 +2077,7 @@ func (s *Session) InviteComplex(inviteID, guildScheduledEventID string, withCoun
endpoint += "?" + v.Encode()
}
- body, err := s.RequestWithBucketID("GET", endpoint, nil, EndpointInvite(""))
+ body, err := s.RequestWithBucketID("GET", endpoint, nil, EndpointInvite(""), options...)
if err != nil {
return
}
@@ -1998,9 +2088,9 @@ func (s *Session) InviteComplex(inviteID, guildScheduledEventID string, withCoun
// InviteDelete deletes an existing invite
// inviteID : the code of an invite
-func (s *Session) InviteDelete(inviteID string) (st *Invite, err error) {
+func (s *Session) InviteDelete(inviteID string, options ...RequestOption) (st *Invite, err error) {
- body, err := s.RequestWithBucketID("DELETE", EndpointInvite(inviteID), nil, EndpointInvite(""))
+ body, err := s.RequestWithBucketID("DELETE", EndpointInvite(inviteID), nil, EndpointInvite(""), options...)
if err != nil {
return
}
@@ -2011,9 +2101,9 @@ func (s *Session) InviteDelete(inviteID string) (st *Invite, err error) {
// InviteAccept accepts an Invite to a Guild or Channel
// inviteID : The invite code
-func (s *Session) InviteAccept(inviteID string) (st *Invite, err error) {
+func (s *Session) InviteAccept(inviteID string, options ...RequestOption) (st *Invite, err error) {
- body, err := s.RequestWithBucketID("POST", EndpointInvite(inviteID), nil, EndpointInvite(""))
+ body, err := s.RequestWithBucketID("POST", EndpointInvite(inviteID), nil, EndpointInvite(""), options...)
if err != nil {
return
}
@@ -2027,9 +2117,9 @@ func (s *Session) InviteAccept(inviteID string) (st *Invite, err error) {
// ------------------------------------------------------------------------------------------------
// VoiceRegions returns the voice server regions
-func (s *Session) VoiceRegions() (st []*VoiceRegion, err error) {
+func (s *Session) VoiceRegions(options ...RequestOption) (st []*VoiceRegion, err error) {
- body, err := s.RequestWithBucketID("GET", EndpointVoiceRegions, nil, EndpointVoiceRegions)
+ body, err := s.RequestWithBucketID("GET", EndpointVoiceRegions, nil, EndpointVoiceRegions, options...)
if err != nil {
return
}
@@ -2043,9 +2133,9 @@ func (s *Session) VoiceRegions() (st []*VoiceRegion, err error) {
// ------------------------------------------------------------------------------------------------
// Gateway returns the websocket Gateway address
-func (s *Session) Gateway() (gateway string, err error) {
+func (s *Session) Gateway(options ...RequestOption) (gateway string, err error) {
- response, err := s.RequestWithBucketID("GET", EndpointGateway, nil, EndpointGateway)
+ response, err := s.RequestWithBucketID("GET", EndpointGateway, nil, EndpointGateway, options...)
if err != nil {
return
}
@@ -2071,9 +2161,9 @@ func (s *Session) Gateway() (gateway string, err error) {
}
// GatewayBot returns the websocket Gateway address and the recommended number of shards
-func (s *Session) GatewayBot() (st *GatewayBotResponse, err error) {
+func (s *Session) GatewayBot(options ...RequestOption) (st *GatewayBotResponse, err error) {
- response, err := s.RequestWithBucketID("GET", EndpointGatewayBot, nil, EndpointGatewayBot)
+ response, err := s.RequestWithBucketID("GET", EndpointGatewayBot, nil, EndpointGatewayBot, options...)
if err != nil {
return
}
@@ -2098,14 +2188,14 @@ func (s *Session) GatewayBot() (st *GatewayBotResponse, err error) {
// channelID: The ID of a Channel.
// name : The name of the webhook.
// avatar : The avatar of the webhook.
-func (s *Session) WebhookCreate(channelID, name, avatar string) (st *Webhook, err error) {
+func (s *Session) WebhookCreate(channelID, name, avatar string, options ...RequestOption) (st *Webhook, err error) {
data := struct {
Name string `json:"name"`
Avatar string `json:"avatar,omitempty"`
}{name, avatar}
- body, err := s.RequestWithBucketID("POST", EndpointChannelWebhooks(channelID), data, EndpointChannelWebhooks(channelID))
+ body, err := s.RequestWithBucketID("POST", EndpointChannelWebhooks(channelID), data, EndpointChannelWebhooks(channelID), options...)
if err != nil {
return
}
@@ -2117,9 +2207,9 @@ func (s *Session) WebhookCreate(channelID, name, avatar string) (st *Webhook, er
// ChannelWebhooks returns all webhooks for a given channel.
// channelID: The ID of a channel.
-func (s *Session) ChannelWebhooks(channelID string) (st []*Webhook, err error) {
+func (s *Session) ChannelWebhooks(channelID string, options ...RequestOption) (st []*Webhook, err error) {
- body, err := s.RequestWithBucketID("GET", EndpointChannelWebhooks(channelID), nil, EndpointChannelWebhooks(channelID))
+ body, err := s.RequestWithBucketID("GET", EndpointChannelWebhooks(channelID), nil, EndpointChannelWebhooks(channelID), options...)
if err != nil {
return
}
@@ -2131,9 +2221,9 @@ func (s *Session) ChannelWebhooks(channelID string) (st []*Webhook, err error) {
// GuildWebhooks returns all webhooks for a given guild.
// guildID: The ID of a Guild.
-func (s *Session) GuildWebhooks(guildID string) (st []*Webhook, err error) {
+func (s *Session) GuildWebhooks(guildID string, options ...RequestOption) (st []*Webhook, err error) {
- body, err := s.RequestWithBucketID("GET", EndpointGuildWebhooks(guildID), nil, EndpointGuildWebhooks(guildID))
+ body, err := s.RequestWithBucketID("GET", EndpointGuildWebhooks(guildID), nil, EndpointGuildWebhooks(guildID), options...)
if err != nil {
return
}
@@ -2145,9 +2235,9 @@ func (s *Session) GuildWebhooks(guildID string) (st []*Webhook, err error) {
// Webhook returns a webhook for a given ID
// webhookID: The ID of a webhook.
-func (s *Session) Webhook(webhookID string) (st *Webhook, err error) {
+func (s *Session) Webhook(webhookID string, options ...RequestOption) (st *Webhook, err error) {
- body, err := s.RequestWithBucketID("GET", EndpointWebhook(webhookID), nil, EndpointWebhooks)
+ body, err := s.RequestWithBucketID("GET", EndpointWebhook(webhookID), nil, EndpointWebhooks, options...)
if err != nil {
return
}
@@ -2160,9 +2250,9 @@ func (s *Session) Webhook(webhookID string) (st *Webhook, err error) {
// WebhookWithToken returns a webhook for a given ID
// webhookID: The ID of a webhook.
// token : The auth token for the webhook.
-func (s *Session) WebhookWithToken(webhookID, token string) (st *Webhook, err error) {
+func (s *Session) WebhookWithToken(webhookID, token string, options ...RequestOption) (st *Webhook, err error) {
- body, err := s.RequestWithBucketID("GET", EndpointWebhookToken(webhookID, token), nil, EndpointWebhookToken("", ""))
+ body, err := s.RequestWithBucketID("GET", EndpointWebhookToken(webhookID, token), nil, EndpointWebhookToken("", ""), options...)
if err != nil {
return
}
@@ -2176,7 +2266,7 @@ func (s *Session) WebhookWithToken(webhookID, token string) (st *Webhook, err er
// webhookID: The ID of a webhook.
// name : The name of the webhook.
// avatar : The avatar of the webhook.
-func (s *Session) WebhookEdit(webhookID, name, avatar, channelID string) (st *Role, err error) {
+func (s *Session) WebhookEdit(webhookID, name, avatar, channelID string, options ...RequestOption) (st *Role, err error) {
data := struct {
Name string `json:"name,omitempty"`
@@ -2184,7 +2274,7 @@ func (s *Session) WebhookEdit(webhookID, name, avatar, channelID string) (st *Ro
ChannelID string `json:"channel_id,omitempty"`
}{name, avatar, channelID}
- body, err := s.RequestWithBucketID("PATCH", EndpointWebhook(webhookID), data, EndpointWebhooks)
+ body, err := s.RequestWithBucketID("PATCH", EndpointWebhook(webhookID), data, EndpointWebhooks, options...)
if err != nil {
return
}
@@ -2199,14 +2289,14 @@ func (s *Session) WebhookEdit(webhookID, name, avatar, channelID string) (st *Ro
// token : The auth token for the webhook.
// name : The name of the webhook.
// avatar : The avatar of the webhook.
-func (s *Session) WebhookEditWithToken(webhookID, token, name, avatar string) (st *Role, err error) {
+func (s *Session) WebhookEditWithToken(webhookID, token, name, avatar string, options ...RequestOption) (st *Role, err error) {
data := struct {
Name string `json:"name,omitempty"`
Avatar string `json:"avatar,omitempty"`
}{name, avatar}
- body, err := s.RequestWithBucketID("PATCH", EndpointWebhookToken(webhookID, token), data, EndpointWebhookToken("", ""))
+ body, err := s.RequestWithBucketID("PATCH", EndpointWebhookToken(webhookID, token), data, EndpointWebhookToken("", ""), options...)
if err != nil {
return
}
@@ -2218,9 +2308,9 @@ func (s *Session) WebhookEditWithToken(webhookID, token, name, avatar string) (s
// WebhookDelete deletes a webhook for a given ID
// webhookID: The ID of a webhook.
-func (s *Session) WebhookDelete(webhookID string) (err error) {
+func (s *Session) WebhookDelete(webhookID string, options ...RequestOption) (err error) {
- _, err = s.RequestWithBucketID("DELETE", EndpointWebhook(webhookID), nil, EndpointWebhooks)
+ _, err = s.RequestWithBucketID("DELETE", EndpointWebhook(webhookID), nil, EndpointWebhooks, options...)
return
}
@@ -2228,9 +2318,9 @@ func (s *Session) WebhookDelete(webhookID string) (err error) {
// WebhookDeleteWithToken deletes a webhook for a given ID with an auth token.
// webhookID: The ID of a webhook.
// token : The auth token for the webhook.
-func (s *Session) WebhookDeleteWithToken(webhookID, token string) (st *Webhook, err error) {
+func (s *Session) WebhookDeleteWithToken(webhookID, token string, options ...RequestOption) (st *Webhook, err error) {
- body, err := s.RequestWithBucketID("DELETE", EndpointWebhookToken(webhookID, token), nil, EndpointWebhookToken("", ""))
+ body, err := s.RequestWithBucketID("DELETE", EndpointWebhookToken(webhookID, token), nil, EndpointWebhookToken("", ""), options...)
if err != nil {
return
}
@@ -2240,7 +2330,7 @@ func (s *Session) WebhookDeleteWithToken(webhookID, token string) (st *Webhook,
return
}
-func (s *Session) webhookExecute(webhookID, token string, wait bool, threadID string, data *WebhookParams) (st *Message, err error) {
+func (s *Session) webhookExecute(webhookID, token string, wait bool, threadID string, data *WebhookParams, options ...RequestOption) (st *Message, err error) {
uri := EndpointWebhookToken(webhookID, token)
v := url.Values{}
@@ -2262,9 +2352,9 @@ func (s *Session) webhookExecute(webhookID, token string, wait bool, threadID st
return st, encodeErr
}
- response, err = s.request("POST", uri, contentType, body, uri, 0)
+ response, err = s.request("POST", uri, contentType, body, uri, 0, options...)
} else {
- response, err = s.RequestWithBucketID("POST", uri, data, uri)
+ response, err = s.RequestWithBucketID("POST", uri, data, uri, options...)
}
if !wait || err != nil {
return
@@ -2278,8 +2368,8 @@ func (s *Session) webhookExecute(webhookID, token string, wait bool, threadID st
// webhookID: The ID of a webhook.
// token : The auth token for the webhook
// wait : Waits for server confirmation of message send and ensures that the return struct is populated (it is nil otherwise)
-func (s *Session) WebhookExecute(webhookID, token string, wait bool, data *WebhookParams) (st *Message, err error) {
- return s.webhookExecute(webhookID, token, wait, "", data)
+func (s *Session) WebhookExecute(webhookID, token string, wait bool, data *WebhookParams, options ...RequestOption) (st *Message, err error) {
+ return s.webhookExecute(webhookID, token, wait, "", data, options...)
}
// WebhookThreadExecute executes a webhook in a thread.
@@ -2287,18 +2377,18 @@ func (s *Session) WebhookExecute(webhookID, token string, wait bool, data *Webho
// token : The auth token for the webhook
// wait : Waits for server confirmation of message send and ensures that the return struct is populated (it is nil otherwise)
// threadID : Sends a message to the specified thread within a webhook's channel. The thread will automatically be unarchived.
-func (s *Session) WebhookThreadExecute(webhookID, token string, wait bool, threadID string, data *WebhookParams) (st *Message, err error) {
- return s.webhookExecute(webhookID, token, wait, threadID, data)
+func (s *Session) WebhookThreadExecute(webhookID, token string, wait bool, threadID string, data *WebhookParams, options ...RequestOption) (st *Message, err error) {
+ return s.webhookExecute(webhookID, token, wait, threadID, data, options...)
}
// WebhookMessage gets a webhook message.
// webhookID : The ID of a webhook
// token : The auth token for the webhook
// messageID : The ID of message to get
-func (s *Session) WebhookMessage(webhookID, token, messageID string) (message *Message, err error) {
+func (s *Session) WebhookMessage(webhookID, token, messageID string, options ...RequestOption) (message *Message, err error) {
uri := EndpointWebhookMessage(webhookID, token, messageID)
- body, err := s.RequestWithBucketID("GET", uri, nil, EndpointWebhookToken("", ""))
+ body, err := s.RequestWithBucketID("GET", uri, nil, EndpointWebhookToken("", ""), options...)
if err != nil {
return
}
@@ -2312,7 +2402,7 @@ func (s *Session) WebhookMessage(webhookID, token, messageID string) (message *M
// webhookID : The ID of a webhook
// token : The auth token for the webhook
// messageID : The ID of message to edit
-func (s *Session) WebhookMessageEdit(webhookID, token, messageID string, data *WebhookEdit) (st *Message, err error) {
+func (s *Session) WebhookMessageEdit(webhookID, token, messageID string, data *WebhookEdit, options ...RequestOption) (st *Message, err error) {
uri := EndpointWebhookMessage(webhookID, token, messageID)
var response []byte
@@ -2322,12 +2412,12 @@ func (s *Session) WebhookMessageEdit(webhookID, token, messageID string, data *W
return nil, err
}
- response, err = s.request("PATCH", uri, contentType, body, uri, 0)
+ response, err = s.request("PATCH", uri, contentType, body, uri, 0, options...)
if err != nil {
return nil, err
}
} else {
- response, err = s.RequestWithBucketID("PATCH", uri, data, EndpointWebhookToken("", ""))
+ response, err = s.RequestWithBucketID("PATCH", uri, data, EndpointWebhookToken("", ""), options...)
if err != nil {
return nil, err
@@ -2342,10 +2432,10 @@ func (s *Session) WebhookMessageEdit(webhookID, token, messageID string, data *W
// webhookID : The ID of a webhook
// token : The auth token for the webhook
// messageID : The ID of a message to edit
-func (s *Session) WebhookMessageDelete(webhookID, token, messageID string) (err error) {
+func (s *Session) WebhookMessageDelete(webhookID, token, messageID string, options ...RequestOption) (err error) {
uri := EndpointWebhookMessage(webhookID, token, messageID)
- _, err = s.RequestWithBucketID("DELETE", uri, nil, EndpointWebhookToken("", ""))
+ _, err = s.RequestWithBucketID("DELETE", uri, nil, EndpointWebhookToken("", ""), options...)
return
}
@@ -2353,11 +2443,11 @@ func (s *Session) WebhookMessageDelete(webhookID, token, messageID string) (err
// channelID : The channel ID.
// messageID : The message ID.
// emojiID : Either the unicode emoji for the reaction, or a guild emoji identifier in name:id format (e.g. "hello:1234567654321")
-func (s *Session) MessageReactionAdd(channelID, messageID, emojiID string) error {
+func (s *Session) MessageReactionAdd(channelID, messageID, emojiID string, options ...RequestOption) error {
// emoji such as #⃣ need to have # escaped
emojiID = strings.Replace(emojiID, "#", "%23", -1)
- _, err := s.RequestWithBucketID("PUT", EndpointMessageReaction(channelID, messageID, emojiID, "@me"), nil, EndpointMessageReaction(channelID, "", "", ""))
+ _, err := s.RequestWithBucketID("PUT", EndpointMessageReaction(channelID, messageID, emojiID, "@me"), nil, EndpointMessageReaction(channelID, "", "", ""), options...)
return err
}
@@ -2367,11 +2457,11 @@ func (s *Session) MessageReactionAdd(channelID, messageID, emojiID string) error
// messageID : The message ID.
// emojiID : Either the unicode emoji for the reaction, or a guild emoji identifier.
// userID : @me or ID of the user to delete the reaction for.
-func (s *Session) MessageReactionRemove(channelID, messageID, emojiID, userID string) error {
+func (s *Session) MessageReactionRemove(channelID, messageID, emojiID, userID string, options ...RequestOption) error {
// emoji such as #⃣ need to have # escaped
emojiID = strings.Replace(emojiID, "#", "%23", -1)
- _, err := s.RequestWithBucketID("DELETE", EndpointMessageReaction(channelID, messageID, emojiID, userID), nil, EndpointMessageReaction(channelID, "", "", ""))
+ _, err := s.RequestWithBucketID("DELETE", EndpointMessageReaction(channelID, messageID, emojiID, userID), nil, EndpointMessageReaction(channelID, "", "", ""), options...)
return err
}
@@ -2379,9 +2469,9 @@ func (s *Session) MessageReactionRemove(channelID, messageID, emojiID, userID st
// MessageReactionsRemoveAll deletes all reactions from a message
// channelID : The channel ID
// messageID : The message ID.
-func (s *Session) MessageReactionsRemoveAll(channelID, messageID string) error {
+func (s *Session) MessageReactionsRemoveAll(channelID, messageID string, options ...RequestOption) error {
- _, err := s.RequestWithBucketID("DELETE", EndpointMessageReactionsAll(channelID, messageID), nil, EndpointMessageReactionsAll(channelID, messageID))
+ _, err := s.RequestWithBucketID("DELETE", EndpointMessageReactionsAll(channelID, messageID), nil, EndpointMessageReactionsAll(channelID, messageID), options...)
return err
}
@@ -2390,11 +2480,11 @@ func (s *Session) MessageReactionsRemoveAll(channelID, messageID string) error {
// channelID : The channel ID
// messageID : The message ID
// emojiID : The emoji ID
-func (s *Session) MessageReactionsRemoveEmoji(channelID, messageID, emojiID string) error {
+func (s *Session) MessageReactionsRemoveEmoji(channelID, messageID, emojiID string, options ...RequestOption) error {
// emoji such as #⃣ need to have # escaped
emojiID = strings.Replace(emojiID, "#", "%23", -1)
- _, err := s.RequestWithBucketID("DELETE", EndpointMessageReactions(channelID, messageID, emojiID), nil, EndpointMessageReactions(channelID, messageID, emojiID))
+ _, err := s.RequestWithBucketID("DELETE", EndpointMessageReactions(channelID, messageID, emojiID), nil, EndpointMessageReactions(channelID, messageID, emojiID), options...)
return err
}
@@ -2406,7 +2496,7 @@ func (s *Session) MessageReactionsRemoveEmoji(channelID, messageID, emojiID stri
// limit : max number of users to return (max 100)
// beforeID : If provided all reactions returned will be before given ID.
// afterID : If provided all reactions returned will be after given ID.
-func (s *Session) MessageReactions(channelID, messageID, emojiID string, limit int, beforeID, afterID string) (st []*User, err error) {
+func (s *Session) MessageReactions(channelID, messageID, emojiID string, limit int, beforeID, afterID string, options ...RequestOption) (st []*User, err error) {
// emoji such as #⃣ need to have # escaped
emojiID = strings.Replace(emojiID, "#", "%23", -1)
uri := EndpointMessageReactions(channelID, messageID, emojiID)
@@ -2428,7 +2518,7 @@ func (s *Session) MessageReactions(channelID, messageID, emojiID string, limit i
uri += "?" + v.Encode()
}
- body, err := s.RequestWithBucketID("GET", uri, nil, EndpointMessageReaction(channelID, "", "", ""))
+ body, err := s.RequestWithBucketID("GET", uri, nil, EndpointMessageReaction(channelID, "", "", ""), options...)
if err != nil {
return
}
@@ -2445,10 +2535,10 @@ func (s *Session) MessageReactions(channelID, messageID, emojiID string, limit i
// channelID : Channel to create thread in
// messageID : Message to start thread from
// data : Parameters of the thread
-func (s *Session) MessageThreadStartComplex(channelID, messageID string, data *ThreadStart) (ch *Channel, err error) {
+func (s *Session) MessageThreadStartComplex(channelID, messageID string, data *ThreadStart, options ...RequestOption) (ch *Channel, err error) {
endpoint := EndpointChannelMessageThread(channelID, messageID)
var body []byte
- body, err = s.RequestWithBucketID("POST", endpoint, data, endpoint)
+ body, err = s.RequestWithBucketID("POST", endpoint, data, endpoint, options...)
if err != nil {
return
}
@@ -2462,20 +2552,20 @@ func (s *Session) MessageThreadStartComplex(channelID, messageID string, data *T
// messageID : Message to start thread from
// name : Name of the thread
// archiveDuration : Auto archive duration (in minutes)
-func (s *Session) MessageThreadStart(channelID, messageID string, name string, archiveDuration int) (ch *Channel, err error) {
+func (s *Session) MessageThreadStart(channelID, messageID string, name string, archiveDuration int, options ...RequestOption) (ch *Channel, err error) {
return s.MessageThreadStartComplex(channelID, messageID, &ThreadStart{
Name: name,
AutoArchiveDuration: archiveDuration,
- })
+ }, options...)
}
// ThreadStartComplex creates a new thread.
// channelID : Channel to create thread in
// data : Parameters of the thread
-func (s *Session) ThreadStartComplex(channelID string, data *ThreadStart) (ch *Channel, err error) {
+func (s *Session) ThreadStartComplex(channelID string, data *ThreadStart, options ...RequestOption) (ch *Channel, err error) {
endpoint := EndpointChannelThreads(channelID)
var body []byte
- body, err = s.RequestWithBucketID("POST", endpoint, data, endpoint)
+ body, err = s.RequestWithBucketID("POST", endpoint, data, endpoint, options...)
if err != nil {
return
}
@@ -2488,47 +2578,141 @@ func (s *Session) ThreadStartComplex(channelID string, data *ThreadStart) (ch *C
// channelID : Channel to create thread in
// name : Name of the thread
// archiveDuration : Auto archive duration (in minutes)
-func (s *Session) ThreadStart(channelID, name string, typ ChannelType, archiveDuration int) (ch *Channel, err error) {
+func (s *Session) ThreadStart(channelID, name string, typ ChannelType, archiveDuration int, options ...RequestOption) (ch *Channel, err error) {
return s.ThreadStartComplex(channelID, &ThreadStart{
Name: name,
Type: typ,
AutoArchiveDuration: archiveDuration,
- })
+ }, options...)
+}
+
+// ForumThreadStartComplex starts a new thread (creates a post) in a forum channel.
+// channelID : Channel to create thread in.
+// threadData : Parameters of the thread.
+// messageData : Parameters of the starting message.
+func (s *Session) ForumThreadStartComplex(channelID string, threadData *ThreadStart, messageData *MessageSend, options ...RequestOption) (th *Channel, err error) {
+ endpoint := EndpointChannelThreads(channelID)
+
+ // TODO: Remove this when compatibility is not required.
+ if messageData.Embed != nil {
+ if messageData.Embeds == nil {
+ messageData.Embeds = []*MessageEmbed{messageData.Embed}
+ } else {
+ err = fmt.Errorf("cannot specify both Embed and Embeds")
+ return
+ }
+ }
+
+ for _, embed := range messageData.Embeds {
+ if embed.Type == "" {
+ embed.Type = "rich"
+ }
+ }
+
+ // TODO: Remove this when compatibility is not required.
+ files := messageData.Files
+ if messageData.File != nil {
+ if files == nil {
+ files = []*File{messageData.File}
+ } else {
+ err = fmt.Errorf("cannot specify both File and Files")
+ return
+ }
+ }
+
+ data := struct {
+ *ThreadStart
+ Message *MessageSend `json:"message"`
+ }{ThreadStart: threadData, Message: messageData}
+
+ var response []byte
+ if len(files) > 0 {
+ contentType, body, encodeErr := MultipartBodyWithJSON(data, files)
+ if encodeErr != nil {
+ return th, encodeErr
+ }
+
+ response, err = s.request("POST", endpoint, contentType, body, endpoint, 0, options...)
+ } else {
+ response, err = s.RequestWithBucketID("POST", endpoint, data, endpoint, options...)
+ }
+ if err != nil {
+ return
+ }
+
+ err = unmarshal(response, &th)
+ return
+}
+
+// ForumThreadStart starts a new thread (post) in a forum channel.
+// channelID : Channel to create thread in.
+// name : Name of the thread.
+// archiveDuration : Auto archive duration.
+// content : Content of the starting message.
+func (s *Session) ForumThreadStart(channelID, name string, archiveDuration int, content string, options ...RequestOption) (th *Channel, err error) {
+ return s.ForumThreadStartComplex(channelID, &ThreadStart{
+ Name: name,
+ AutoArchiveDuration: archiveDuration,
+ }, &MessageSend{Content: content}, options...)
+}
+
+// ForumThreadStartEmbed starts a new thread (post) in a forum channel.
+// channelID : Channel to create thread in.
+// name : Name of the thread.
+// archiveDuration : Auto archive duration.
+// embed : Embed data of the starting message.
+func (s *Session) ForumThreadStartEmbed(channelID, name string, archiveDuration int, embed *MessageEmbed, options ...RequestOption) (th *Channel, err error) {
+ return s.ForumThreadStartComplex(channelID, &ThreadStart{
+ Name: name,
+ AutoArchiveDuration: archiveDuration,
+ }, &MessageSend{Embeds: []*MessageEmbed{embed}}, options...)
+}
+
+// ForumThreadStartEmbeds starts a new thread (post) in a forum channel.
+// channelID : Channel to create thread in.
+// name : Name of the thread.
+// archiveDuration : Auto archive duration.
+// embeds : Embeds data of the starting message.
+func (s *Session) ForumThreadStartEmbeds(channelID, name string, archiveDuration int, embeds []*MessageEmbed, options ...RequestOption) (th *Channel, err error) {
+ return s.ForumThreadStartComplex(channelID, &ThreadStart{
+ Name: name,
+ AutoArchiveDuration: archiveDuration,
+ }, &MessageSend{Embeds: embeds}, options...)
}
// ThreadJoin adds current user to a thread
-func (s *Session) ThreadJoin(id string) error {
+func (s *Session) ThreadJoin(id string, options ...RequestOption) error {
endpoint := EndpointThreadMember(id, "@me")
- _, err := s.RequestWithBucketID("PUT", endpoint, nil, endpoint)
+ _, err := s.RequestWithBucketID("PUT", endpoint, nil, endpoint, options...)
return err
}
// ThreadLeave removes current user to a thread
-func (s *Session) ThreadLeave(id string) error {
+func (s *Session) ThreadLeave(id string, options ...RequestOption) error {
endpoint := EndpointThreadMember(id, "@me")
- _, err := s.RequestWithBucketID("DELETE", endpoint, nil, endpoint)
+ _, err := s.RequestWithBucketID("DELETE", endpoint, nil, endpoint, options...)
return err
}
// ThreadMemberAdd adds another member to a thread
-func (s *Session) ThreadMemberAdd(threadID, memberID string) error {
+func (s *Session) ThreadMemberAdd(threadID, memberID string, options ...RequestOption) error {
endpoint := EndpointThreadMember(threadID, memberID)
- _, err := s.RequestWithBucketID("PUT", endpoint, nil, endpoint)
+ _, err := s.RequestWithBucketID("PUT", endpoint, nil, endpoint, options...)
return err
}
// ThreadMemberRemove removes another member from a thread
-func (s *Session) ThreadMemberRemove(threadID, memberID string) error {
+func (s *Session) ThreadMemberRemove(threadID, memberID string, options ...RequestOption) error {
endpoint := EndpointThreadMember(threadID, memberID)
- _, err := s.RequestWithBucketID("DELETE", endpoint, nil, endpoint)
+ _, err := s.RequestWithBucketID("DELETE", endpoint, nil, endpoint, options...)
return err
}
// ThreadMember returns thread member object for the specified member of a thread
-func (s *Session) ThreadMember(threadID, memberID string) (member *ThreadMember, err error) {
+func (s *Session) ThreadMember(threadID, memberID string, options ...RequestOption) (member *ThreadMember, err error) {
endpoint := EndpointThreadMember(threadID, memberID)
var body []byte
- body, err = s.RequestWithBucketID("GET", endpoint, nil, endpoint)
+ body, err = s.RequestWithBucketID("GET", endpoint, nil, endpoint, options...)
if err != nil {
return
@@ -2539,9 +2723,9 @@ func (s *Session) ThreadMember(threadID, memberID string) (member *ThreadMember,
}
// ThreadMembers returns all members of specified thread.
-func (s *Session) ThreadMembers(threadID string) (members []*ThreadMember, err error) {
+func (s *Session) ThreadMembers(threadID string, options ...RequestOption) (members []*ThreadMember, err error) {
var body []byte
- body, err = s.RequestWithBucketID("GET", EndpointThreadMembers(threadID), nil, EndpointThreadMembers(threadID))
+ body, err = s.RequestWithBucketID("GET", EndpointThreadMembers(threadID), nil, EndpointThreadMembers(threadID), options...)
if err != nil {
return
@@ -2552,9 +2736,9 @@ func (s *Session) ThreadMembers(threadID string) (members []*ThreadMember, err e
}
// ThreadsActive returns all active threads for specified channel.
-func (s *Session) ThreadsActive(channelID string) (threads *ThreadsList, err error) {
+func (s *Session) ThreadsActive(channelID string, options ...RequestOption) (threads *ThreadsList, err error) {
var body []byte
- body, err = s.RequestWithBucketID("GET", EndpointChannelActiveThreads(channelID), nil, EndpointChannelActiveThreads(channelID))
+ body, err = s.RequestWithBucketID("GET", EndpointChannelActiveThreads(channelID), nil, EndpointChannelActiveThreads(channelID), options...)
if err != nil {
return
}
@@ -2564,9 +2748,9 @@ func (s *Session) ThreadsActive(channelID string) (threads *ThreadsList, err err
}
// GuildThreadsActive returns all active threads for specified guild.
-func (s *Session) GuildThreadsActive(guildID string) (threads *ThreadsList, err error) {
+func (s *Session) GuildThreadsActive(guildID string, options ...RequestOption) (threads *ThreadsList, err error) {
var body []byte
- body, err = s.RequestWithBucketID("GET", EndpointGuildActiveThreads(guildID), nil, EndpointGuildActiveThreads(guildID))
+ body, err = s.RequestWithBucketID("GET", EndpointGuildActiveThreads(guildID), nil, EndpointGuildActiveThreads(guildID), options...)
if err != nil {
return
}
@@ -2578,7 +2762,7 @@ func (s *Session) GuildThreadsActive(guildID string) (threads *ThreadsList, err
// ThreadsArchived returns archived threads for specified channel.
// before : If specified returns only threads before the timestamp
// limit : Optional maximum amount of threads to return.
-func (s *Session) ThreadsArchived(channelID string, before *time.Time, limit int) (threads *ThreadsList, err error) {
+func (s *Session) ThreadsArchived(channelID string, before *time.Time, limit int, options ...RequestOption) (threads *ThreadsList, err error) {
endpoint := EndpointChannelPublicArchivedThreads(channelID)
v := url.Values{}
if before != nil {
@@ -2594,7 +2778,7 @@ func (s *Session) ThreadsArchived(channelID string, before *time.Time, limit int
}
var body []byte
- body, err = s.RequestWithBucketID("GET", endpoint, nil, endpoint)
+ body, err = s.RequestWithBucketID("GET", endpoint, nil, endpoint, options...)
if err != nil {
return
}
@@ -2606,7 +2790,7 @@ func (s *Session) ThreadsArchived(channelID string, before *time.Time, limit int
// ThreadsPrivateArchived returns archived private threads for specified channel.
// before : If specified returns only threads before the timestamp
// limit : Optional maximum amount of threads to return.
-func (s *Session) ThreadsPrivateArchived(channelID string, before *time.Time, limit int) (threads *ThreadsList, err error) {
+func (s *Session) ThreadsPrivateArchived(channelID string, before *time.Time, limit int, options ...RequestOption) (threads *ThreadsList, err error) {
endpoint := EndpointChannelPrivateArchivedThreads(channelID)
v := url.Values{}
if before != nil {
@@ -2621,7 +2805,7 @@ func (s *Session) ThreadsPrivateArchived(channelID string, before *time.Time, li
endpoint += "?" + v.Encode()
}
var body []byte
- body, err = s.RequestWithBucketID("GET", endpoint, nil, endpoint)
+ body, err = s.RequestWithBucketID("GET", endpoint, nil, endpoint, options...)
if err != nil {
return
}
@@ -2633,7 +2817,7 @@ func (s *Session) ThreadsPrivateArchived(channelID string, before *time.Time, li
// ThreadsPrivateJoinedArchived returns archived joined private threads for specified channel.
// before : If specified returns only threads before the timestamp
// limit : Optional maximum amount of threads to return.
-func (s *Session) ThreadsPrivateJoinedArchived(channelID string, before *time.Time, limit int) (threads *ThreadsList, err error) {
+func (s *Session) ThreadsPrivateJoinedArchived(channelID string, before *time.Time, limit int, options ...RequestOption) (threads *ThreadsList, err error) {
endpoint := EndpointChannelJoinedPrivateArchivedThreads(channelID)
v := url.Values{}
if before != nil {
@@ -2648,7 +2832,7 @@ func (s *Session) ThreadsPrivateJoinedArchived(channelID string, before *time.Ti
endpoint += "?" + v.Encode()
}
var body []byte
- body, err = s.RequestWithBucketID("GET", endpoint, nil, endpoint)
+ body, err = s.RequestWithBucketID("GET", endpoint, nil, endpoint, options...)
if err != nil {
return
}
@@ -2665,13 +2849,13 @@ func (s *Session) ThreadsPrivateJoinedArchived(channelID string, before *time.Ti
// appID : The application ID.
// guildID : Guild ID to create guild-specific application command. If empty - creates global application command.
// cmd : New application command data.
-func (s *Session) ApplicationCommandCreate(appID string, guildID string, cmd *ApplicationCommand) (ccmd *ApplicationCommand, err error) {
+func (s *Session) ApplicationCommandCreate(appID string, guildID string, cmd *ApplicationCommand, options ...RequestOption) (ccmd *ApplicationCommand, err error) {
endpoint := EndpointApplicationGlobalCommands(appID)
if guildID != "" {
endpoint = EndpointApplicationGuildCommands(appID, guildID)
}
- body, err := s.RequestWithBucketID("POST", endpoint, *cmd, endpoint)
+ body, err := s.RequestWithBucketID("POST", endpoint, *cmd, endpoint, options...)
if err != nil {
return
}
@@ -2686,13 +2870,13 @@ func (s *Session) ApplicationCommandCreate(appID string, guildID string, cmd *Ap
// cmdID : Application command ID to edit.
// guildID : Guild ID to edit guild-specific application command. If empty - edits global application command.
// cmd : Updated application command data.
-func (s *Session) ApplicationCommandEdit(appID, guildID, cmdID string, cmd *ApplicationCommand) (updated *ApplicationCommand, err error) {
+func (s *Session) ApplicationCommandEdit(appID, guildID, cmdID string, cmd *ApplicationCommand, options ...RequestOption) (updated *ApplicationCommand, err error) {
endpoint := EndpointApplicationGlobalCommand(appID, cmdID)
if guildID != "" {
endpoint = EndpointApplicationGuildCommand(appID, guildID, cmdID)
}
- body, err := s.RequestWithBucketID("PATCH", endpoint, *cmd, endpoint)
+ body, err := s.RequestWithBucketID("PATCH", endpoint, *cmd, endpoint, options...)
if err != nil {
return
}
@@ -2705,13 +2889,13 @@ func (s *Session) ApplicationCommandEdit(appID, guildID, cmdID string, cmd *Appl
// ApplicationCommandBulkOverwrite Creates commands overwriting existing commands. Returns a list of commands.
// appID : The application ID.
// commands : The commands to create.
-func (s *Session) ApplicationCommandBulkOverwrite(appID string, guildID string, commands []*ApplicationCommand) (createdCommands []*ApplicationCommand, err error) {
+func (s *Session) ApplicationCommandBulkOverwrite(appID string, guildID string, commands []*ApplicationCommand, options ...RequestOption) (createdCommands []*ApplicationCommand, err error) {
endpoint := EndpointApplicationGlobalCommands(appID)
if guildID != "" {
endpoint = EndpointApplicationGuildCommands(appID, guildID)
}
- body, err := s.RequestWithBucketID("PUT", endpoint, commands, endpoint)
+ body, err := s.RequestWithBucketID("PUT", endpoint, commands, endpoint, options...)
if err != nil {
return
}
@@ -2725,13 +2909,13 @@ func (s *Session) ApplicationCommandBulkOverwrite(appID string, guildID string,
// appID : The application ID.
// cmdID : Application command ID to delete.
// guildID : Guild ID to delete guild-specific application command. If empty - deletes global application command.
-func (s *Session) ApplicationCommandDelete(appID, guildID, cmdID string) error {
+func (s *Session) ApplicationCommandDelete(appID, guildID, cmdID string, options ...RequestOption) error {
endpoint := EndpointApplicationGlobalCommand(appID, cmdID)
if guildID != "" {
endpoint = EndpointApplicationGuildCommand(appID, guildID, cmdID)
}
- _, err := s.RequestWithBucketID("DELETE", endpoint, nil, endpoint)
+ _, err := s.RequestWithBucketID("DELETE", endpoint, nil, endpoint, options...)
return err
}
@@ -2740,13 +2924,13 @@ func (s *Session) ApplicationCommandDelete(appID, guildID, cmdID string) error {
// appID : The application ID.
// cmdID : Application command ID.
// guildID : Guild ID to retrieve guild-specific application command. If empty - retrieves global application command.
-func (s *Session) ApplicationCommand(appID, guildID, cmdID string) (cmd *ApplicationCommand, err error) {
+func (s *Session) ApplicationCommand(appID, guildID, cmdID string, options ...RequestOption) (cmd *ApplicationCommand, err error) {
endpoint := EndpointApplicationGlobalCommand(appID, cmdID)
if guildID != "" {
endpoint = EndpointApplicationGuildCommand(appID, guildID, cmdID)
}
- body, err := s.RequestWithBucketID("GET", endpoint, nil, endpoint)
+ body, err := s.RequestWithBucketID("GET", endpoint, nil, endpoint, options...)
if err != nil {
return
}
@@ -2759,13 +2943,13 @@ func (s *Session) ApplicationCommand(appID, guildID, cmdID string) (cmd *Applica
// ApplicationCommands retrieves all commands in application.
// appID : The application ID.
// guildID : Guild ID to retrieve all guild-specific application commands. If empty - retrieves global application commands.
-func (s *Session) ApplicationCommands(appID, guildID string) (cmd []*ApplicationCommand, err error) {
+func (s *Session) ApplicationCommands(appID, guildID string, options ...RequestOption) (cmd []*ApplicationCommand, err error) {
endpoint := EndpointApplicationGlobalCommands(appID)
if guildID != "" {
endpoint = EndpointApplicationGuildCommands(appID, guildID)
}
- body, err := s.RequestWithBucketID("GET", endpoint+"?with_localizations=true", nil, "GET "+endpoint)
+ body, err := s.RequestWithBucketID("GET", endpoint+"?with_localizations=true", nil, "GET "+endpoint, options...)
if err != nil {
return
}
@@ -2778,11 +2962,11 @@ func (s *Session) ApplicationCommands(appID, guildID string) (cmd []*Application
// GuildApplicationCommandsPermissions returns permissions for application commands in a guild.
// appID : The application ID
// guildID : Guild ID to retrieve application commands permissions for.
-func (s *Session) GuildApplicationCommandsPermissions(appID, guildID string) (permissions []*GuildApplicationCommandPermissions, err error) {
+func (s *Session) GuildApplicationCommandsPermissions(appID, guildID string, options ...RequestOption) (permissions []*GuildApplicationCommandPermissions, err error) {
endpoint := EndpointApplicationCommandsGuildPermissions(appID, guildID)
var body []byte
- body, err = s.RequestWithBucketID("GET", endpoint, nil, endpoint)
+ body, err = s.RequestWithBucketID("GET", endpoint, nil, endpoint, options...)
if err != nil {
return
}
@@ -2795,11 +2979,11 @@ func (s *Session) GuildApplicationCommandsPermissions(appID, guildID string) (pe
// appID : The Application ID
// guildID : The guild ID containing the application command
// cmdID : The command ID to retrieve the permissions of
-func (s *Session) ApplicationCommandPermissions(appID, guildID, cmdID string) (permissions *GuildApplicationCommandPermissions, err error) {
+func (s *Session) ApplicationCommandPermissions(appID, guildID, cmdID string, options ...RequestOption) (permissions *GuildApplicationCommandPermissions, err error) {
endpoint := EndpointApplicationCommandPermissions(appID, guildID, cmdID)
var body []byte
- body, err = s.RequestWithBucketID("GET", endpoint, nil, endpoint)
+ body, err = s.RequestWithBucketID("GET", endpoint, nil, endpoint, options...)
if err != nil {
return
}
@@ -2815,10 +2999,10 @@ func (s *Session) ApplicationCommandPermissions(appID, guildID, cmdID string) (p
// permissions : An object containing a list of permissions for the application command
//
// NOTE: Requires OAuth2 token with applications.commands.permissions.update scope
-func (s *Session) ApplicationCommandPermissionsEdit(appID, guildID, cmdID string, permissions *ApplicationCommandPermissionsList) (err error) {
+func (s *Session) ApplicationCommandPermissionsEdit(appID, guildID, cmdID string, permissions *ApplicationCommandPermissionsList, options ...RequestOption) (err error) {
endpoint := EndpointApplicationCommandPermissions(appID, guildID, cmdID)
- _, err = s.RequestWithBucketID("PUT", endpoint, permissions, endpoint)
+ _, err = s.RequestWithBucketID("PUT", endpoint, permissions, endpoint, options...)
return
}
@@ -2828,17 +3012,17 @@ func (s *Session) ApplicationCommandPermissionsEdit(appID, guildID, cmdID string
// permissions : A list of permissions paired with a command ID, guild ID, and application ID per application command
//
// NOTE: This endpoint has been disabled with updates to command permissions (Permissions v2). Please use ApplicationCommandPermissionsEdit instead.
-func (s *Session) ApplicationCommandPermissionsBatchEdit(appID, guildID string, permissions []*GuildApplicationCommandPermissions) (err error) {
+func (s *Session) ApplicationCommandPermissionsBatchEdit(appID, guildID string, permissions []*GuildApplicationCommandPermissions, options ...RequestOption) (err error) {
endpoint := EndpointApplicationCommandsGuildPermissions(appID, guildID)
- _, err = s.RequestWithBucketID("PUT", endpoint, permissions, endpoint)
+ _, err = s.RequestWithBucketID("PUT", endpoint, permissions, endpoint, options...)
return
}
// InteractionRespond creates the response to an interaction.
// interaction : Interaction instance.
// resp : Response message data.
-func (s *Session) InteractionRespond(interaction *Interaction, resp *InteractionResponse) error {
+func (s *Session) InteractionRespond(interaction *Interaction, resp *InteractionResponse, options ...RequestOption) error {
endpoint := EndpointInteractionResponse(interaction.ID, interaction.Token)
if resp.Data != nil && len(resp.Data.Files) > 0 {
@@ -2847,33 +3031,33 @@ func (s *Session) InteractionRespond(interaction *Interaction, resp *Interaction
return err
}
- _, err = s.request("POST", endpoint, contentType, body, endpoint, 0)
+ _, err = s.request("POST", endpoint, contentType, body, endpoint, 0, options...)
return err
}
- _, err := s.RequestWithBucketID("POST", endpoint, *resp, endpoint)
+ _, err := s.RequestWithBucketID("POST", endpoint, *resp, endpoint, options...)
return err
}
// InteractionResponse gets the response to an interaction.
// interaction : Interaction instance.
-func (s *Session) InteractionResponse(interaction *Interaction) (*Message, error) {
- return s.WebhookMessage(interaction.AppID, interaction.Token, "@original")
+func (s *Session) InteractionResponse(interaction *Interaction, options ...RequestOption) (*Message, error) {
+ return s.WebhookMessage(interaction.AppID, interaction.Token, "@original", options...)
}
// InteractionResponseEdit edits the response to an interaction.
// interaction : Interaction instance.
// newresp : Updated response message data.
-func (s *Session) InteractionResponseEdit(interaction *Interaction, newresp *WebhookEdit) (*Message, error) {
- return s.WebhookMessageEdit(interaction.AppID, interaction.Token, "@original", newresp)
+func (s *Session) InteractionResponseEdit(interaction *Interaction, newresp *WebhookEdit, options ...RequestOption) (*Message, error) {
+ return s.WebhookMessageEdit(interaction.AppID, interaction.Token, "@original", newresp, options...)
}
// InteractionResponseDelete deletes the response to an interaction.
// interaction : Interaction instance.
-func (s *Session) InteractionResponseDelete(interaction *Interaction) error {
+func (s *Session) InteractionResponseDelete(interaction *Interaction, options ...RequestOption) error {
endpoint := EndpointInteractionResponseActions(interaction.AppID, interaction.Token)
- _, err := s.RequestWithBucketID("DELETE", endpoint, nil, endpoint)
+ _, err := s.RequestWithBucketID("DELETE", endpoint, nil, endpoint, options...)
return err
}
@@ -2882,23 +3066,23 @@ func (s *Session) InteractionResponseDelete(interaction *Interaction) error {
// interaction : Interaction instance.
// wait : Waits for server confirmation of message send and ensures that the return struct is populated (it is nil otherwise)
// data : Data of the message to send.
-func (s *Session) FollowupMessageCreate(interaction *Interaction, wait bool, data *WebhookParams) (*Message, error) {
- return s.WebhookExecute(interaction.AppID, interaction.Token, wait, data)
+func (s *Session) FollowupMessageCreate(interaction *Interaction, wait bool, data *WebhookParams, options ...RequestOption) (*Message, error) {
+ return s.WebhookExecute(interaction.AppID, interaction.Token, wait, data, options...)
}
// FollowupMessageEdit edits a followup message of an interaction.
// interaction : Interaction instance.
// messageID : The followup message ID.
// data : Data to update the message
-func (s *Session) FollowupMessageEdit(interaction *Interaction, messageID string, data *WebhookEdit) (*Message, error) {
- return s.WebhookMessageEdit(interaction.AppID, interaction.Token, messageID, data)
+func (s *Session) FollowupMessageEdit(interaction *Interaction, messageID string, data *WebhookEdit, options ...RequestOption) (*Message, error) {
+ return s.WebhookMessageEdit(interaction.AppID, interaction.Token, messageID, data, options...)
}
// FollowupMessageDelete deletes a followup message of an interaction.
// interaction : Interaction instance.
// messageID : The followup message ID.
-func (s *Session) FollowupMessageDelete(interaction *Interaction, messageID string) error {
- return s.WebhookMessageDelete(interaction.AppID, interaction.Token, messageID)
+func (s *Session) FollowupMessageDelete(interaction *Interaction, messageID string, options ...RequestOption) error {
+ return s.WebhookMessageDelete(interaction.AppID, interaction.Token, messageID, options...)
}
// ------------------------------------------------------------------------------------------------
@@ -2908,8 +3092,8 @@ func (s *Session) FollowupMessageDelete(interaction *Interaction, messageID stri
// StageInstanceCreate creates and returns a new Stage instance associated to a Stage channel.
// data : Parameters needed to create a stage instance.
// data : The data of the Stage instance to create
-func (s *Session) StageInstanceCreate(data *StageInstanceParams) (si *StageInstance, err error) {
- body, err := s.RequestWithBucketID("POST", EndpointStageInstances, data, EndpointStageInstances)
+func (s *Session) StageInstanceCreate(data *StageInstanceParams, options ...RequestOption) (si *StageInstance, err error) {
+ body, err := s.RequestWithBucketID("POST", EndpointStageInstances, data, EndpointStageInstances, options...)
if err != nil {
return
}
@@ -2920,8 +3104,8 @@ func (s *Session) StageInstanceCreate(data *StageInstanceParams) (si *StageInsta
// StageInstance will retrieve a Stage instance by ID of the Stage channel.
// channelID : The ID of the Stage channel
-func (s *Session) StageInstance(channelID string) (si *StageInstance, err error) {
- body, err := s.RequestWithBucketID("GET", EndpointStageInstance(channelID), nil, EndpointStageInstance(channelID))
+func (s *Session) StageInstance(channelID string, options ...RequestOption) (si *StageInstance, err error) {
+ body, err := s.RequestWithBucketID("GET", EndpointStageInstance(channelID), nil, EndpointStageInstance(channelID), options...)
if err != nil {
return
}
@@ -2933,9 +3117,9 @@ func (s *Session) StageInstance(channelID string) (si *StageInstance, err error)
// StageInstanceEdit will edit a Stage instance by ID of the Stage channel.
// channelID : The ID of the Stage channel
// data : The data to edit the Stage instance
-func (s *Session) StageInstanceEdit(channelID string, data *StageInstanceParams) (si *StageInstance, err error) {
+func (s *Session) StageInstanceEdit(channelID string, data *StageInstanceParams, options ...RequestOption) (si *StageInstance, err error) {
- body, err := s.RequestWithBucketID("PATCH", EndpointStageInstance(channelID), data, EndpointStageInstance(channelID))
+ body, err := s.RequestWithBucketID("PATCH", EndpointStageInstance(channelID), data, EndpointStageInstance(channelID), options...)
if err != nil {
return
}
@@ -2946,8 +3130,8 @@ func (s *Session) StageInstanceEdit(channelID string, data *StageInstanceParams)
// StageInstanceDelete will delete a Stage instance by ID of the Stage channel.
// channelID : The ID of the Stage channel
-func (s *Session) StageInstanceDelete(channelID string) (err error) {
- _, err = s.RequestWithBucketID("DELETE", EndpointStageInstance(channelID), nil, EndpointStageInstance(channelID))
+func (s *Session) StageInstanceDelete(channelID string, options ...RequestOption) (err error) {
+ _, err = s.RequestWithBucketID("DELETE", EndpointStageInstance(channelID), nil, EndpointStageInstance(channelID), options...)
return
}
@@ -2958,13 +3142,13 @@ func (s *Session) StageInstanceDelete(channelID string) (err error) {
// GuildScheduledEvents returns an array of GuildScheduledEvent for a guild
// guildID : The ID of a Guild
// userCount : Whether to include the user count in the response
-func (s *Session) GuildScheduledEvents(guildID string, userCount bool) (st []*GuildScheduledEvent, err error) {
+func (s *Session) GuildScheduledEvents(guildID string, userCount bool, options ...RequestOption) (st []*GuildScheduledEvent, err error) {
uri := EndpointGuildScheduledEvents(guildID)
if userCount {
uri += "?with_user_count=true"
}
- body, err := s.RequestWithBucketID("GET", uri, nil, EndpointGuildScheduledEvents(guildID))
+ body, err := s.RequestWithBucketID("GET", uri, nil, EndpointGuildScheduledEvents(guildID), options...)
if err != nil {
return
}
@@ -2977,13 +3161,13 @@ func (s *Session) GuildScheduledEvents(guildID string, userCount bool) (st []*Gu
// guildID : The ID of a Guild
// eventID : The ID of the event
// userCount : Whether to include the user count in the response
-func (s *Session) GuildScheduledEvent(guildID, eventID string, userCount bool) (st *GuildScheduledEvent, err error) {
+func (s *Session) GuildScheduledEvent(guildID, eventID string, userCount bool, options ...RequestOption) (st *GuildScheduledEvent, err error) {
uri := EndpointGuildScheduledEvent(guildID, eventID)
if userCount {
uri += "?with_user_count=true"
}
- body, err := s.RequestWithBucketID("GET", uri, nil, EndpointGuildScheduledEvent(guildID, eventID))
+ body, err := s.RequestWithBucketID("GET", uri, nil, EndpointGuildScheduledEvent(guildID, eventID), options...)
if err != nil {
return
}
@@ -2995,8 +3179,8 @@ func (s *Session) GuildScheduledEvent(guildID, eventID string, userCount bool) (
// GuildScheduledEventCreate creates a GuildScheduledEvent for a guild and returns it
// guildID : The ID of a Guild
// eventID : The ID of the event
-func (s *Session) GuildScheduledEventCreate(guildID string, event *GuildScheduledEventParams) (st *GuildScheduledEvent, err error) {
- body, err := s.RequestWithBucketID("POST", EndpointGuildScheduledEvents(guildID), event, EndpointGuildScheduledEvents(guildID))
+func (s *Session) GuildScheduledEventCreate(guildID string, event *GuildScheduledEventParams, options ...RequestOption) (st *GuildScheduledEvent, err error) {
+ body, err := s.RequestWithBucketID("POST", EndpointGuildScheduledEvents(guildID), event, EndpointGuildScheduledEvents(guildID), options...)
if err != nil {
return
}
@@ -3008,8 +3192,8 @@ func (s *Session) GuildScheduledEventCreate(guildID string, event *GuildSchedule
// GuildScheduledEventEdit updates a specific event for a guild and returns it.
// guildID : The ID of a Guild
// eventID : The ID of the event
-func (s *Session) GuildScheduledEventEdit(guildID, eventID string, event *GuildScheduledEventParams) (st *GuildScheduledEvent, err error) {
- body, err := s.RequestWithBucketID("PATCH", EndpointGuildScheduledEvent(guildID, eventID), event, EndpointGuildScheduledEvent(guildID, eventID))
+func (s *Session) GuildScheduledEventEdit(guildID, eventID string, event *GuildScheduledEventParams, options ...RequestOption) (st *GuildScheduledEvent, err error) {
+ body, err := s.RequestWithBucketID("PATCH", EndpointGuildScheduledEvent(guildID, eventID), event, EndpointGuildScheduledEvent(guildID, eventID), options...)
if err != nil {
return
}
@@ -3021,8 +3205,8 @@ func (s *Session) GuildScheduledEventEdit(guildID, eventID string, event *GuildS
// GuildScheduledEventDelete deletes a specific GuildScheduledEvent in a guild
// guildID : The ID of a Guild
// eventID : The ID of the event
-func (s *Session) GuildScheduledEventDelete(guildID, eventID string) (err error) {
- _, err = s.RequestWithBucketID("DELETE", EndpointGuildScheduledEvent(guildID, eventID), nil, EndpointGuildScheduledEvent(guildID, eventID))
+func (s *Session) GuildScheduledEventDelete(guildID, eventID string, options ...RequestOption) (err error) {
+ _, err = s.RequestWithBucketID("DELETE", EndpointGuildScheduledEvent(guildID, eventID), nil, EndpointGuildScheduledEvent(guildID, eventID), options...)
return
}
@@ -3033,7 +3217,7 @@ func (s *Session) GuildScheduledEventDelete(guildID, eventID string) (err error)
// withMember : Whether to include the member object in the response
// beforeID : If is not empty all returned users entries will be before the given ID
// afterID : If is not empty all returned users entries will be after the given ID
-func (s *Session) GuildScheduledEventUsers(guildID, eventID string, limit int, withMember bool, beforeID, afterID string) (st []*GuildScheduledEventUser, err error) {
+func (s *Session) GuildScheduledEventUsers(guildID, eventID string, limit int, withMember bool, beforeID, afterID string, options ...RequestOption) (st []*GuildScheduledEventUser, err error) {
uri := EndpointGuildScheduledEventUsers(guildID, eventID)
queryParams := url.Values{}
@@ -3054,7 +3238,7 @@ func (s *Session) GuildScheduledEventUsers(guildID, eventID string, limit int, w
uri += "?" + queryParams.Encode()
}
- body, err := s.RequestWithBucketID("GET", uri, nil, EndpointGuildScheduledEventUsers(guildID, eventID))
+ body, err := s.RequestWithBucketID("GET", uri, nil, EndpointGuildScheduledEventUsers(guildID, eventID), options...)
if err != nil {
return
}
@@ -3069,11 +3253,11 @@ func (s *Session) GuildScheduledEventUsers(guildID, eventID string, limit int, w
// AutoModerationRules returns a list of auto moderation rules.
// guildID : ID of the guild
-func (s *Session) AutoModerationRules(guildID string) (st []*AutoModerationRule, err error) {
+func (s *Session) AutoModerationRules(guildID string, options ...RequestOption) (st []*AutoModerationRule, err error) {
endpoint := EndpointGuildAutoModerationRules(guildID)
var body []byte
- body, err = s.RequestWithBucketID("GET", endpoint, nil, endpoint)
+ body, err = s.RequestWithBucketID("GET", endpoint, nil, endpoint, options...)
if err != nil {
return
}
@@ -3085,11 +3269,11 @@ func (s *Session) AutoModerationRules(guildID string) (st []*AutoModerationRule,
// AutoModerationRule returns an auto moderation rule.
// guildID : ID of the guild
// ruleID : ID of the auto moderation rule
-func (s *Session) AutoModerationRule(guildID, ruleID string) (st *AutoModerationRule, err error) {
+func (s *Session) AutoModerationRule(guildID, ruleID string, options ...RequestOption) (st *AutoModerationRule, err error) {
endpoint := EndpointGuildAutoModerationRule(guildID, ruleID)
var body []byte
- body, err = s.RequestWithBucketID("GET", endpoint, nil, endpoint)
+ body, err = s.RequestWithBucketID("GET", endpoint, nil, endpoint, options...)
if err != nil {
return
}
@@ -3101,11 +3285,11 @@ func (s *Session) AutoModerationRule(guildID, ruleID string) (st *AutoModeration
// AutoModerationRuleCreate creates an auto moderation rule with the given data and returns it.
// guildID : ID of the guild
// rule : Rule data
-func (s *Session) AutoModerationRuleCreate(guildID string, rule *AutoModerationRule) (st *AutoModerationRule, err error) {
+func (s *Session) AutoModerationRuleCreate(guildID string, rule *AutoModerationRule, options ...RequestOption) (st *AutoModerationRule, err error) {
endpoint := EndpointGuildAutoModerationRules(guildID)
var body []byte
- body, err = s.RequestWithBucketID("POST", endpoint, rule, endpoint)
+ body, err = s.RequestWithBucketID("POST", endpoint, rule, endpoint, options...)
if err != nil {
return
}
@@ -3118,11 +3302,11 @@ func (s *Session) AutoModerationRuleCreate(guildID string, rule *AutoModerationR
// guildID : ID of the guild
// ruleID : ID of the auto moderation rule
// rule : New rule data
-func (s *Session) AutoModerationRuleEdit(guildID, ruleID string, rule *AutoModerationRule) (st *AutoModerationRule, err error) {
+func (s *Session) AutoModerationRuleEdit(guildID, ruleID string, rule *AutoModerationRule, options ...RequestOption) (st *AutoModerationRule, err error) {
endpoint := EndpointGuildAutoModerationRule(guildID, ruleID)
var body []byte
- body, err = s.RequestWithBucketID("PATCH", endpoint, rule, endpoint)
+ body, err = s.RequestWithBucketID("PATCH", endpoint, rule, endpoint, options...)
if err != nil {
return
}
@@ -3134,8 +3318,67 @@ func (s *Session) AutoModerationRuleEdit(guildID, ruleID string, rule *AutoModer
// AutoModerationRuleDelete deletes an auto moderation rule.
// guildID : ID of the guild
// ruleID : ID of the auto moderation rule
-func (s *Session) AutoModerationRuleDelete(guildID, ruleID string) (err error) {
+func (s *Session) AutoModerationRuleDelete(guildID, ruleID string, options ...RequestOption) (err error) {
endpoint := EndpointGuildAutoModerationRule(guildID, ruleID)
- _, err = s.RequestWithBucketID("DELETE", endpoint, nil, endpoint)
+ _, err = s.RequestWithBucketID("DELETE", endpoint, nil, endpoint, options...)
+ return
+}
+
+// ApplicationRoleConnectionMetadata returns application role connection metadata.
+// appID : ID of the application
+func (s *Session) ApplicationRoleConnectionMetadata(appID string) (st []*ApplicationRoleConnectionMetadata, err error) {
+ endpoint := EndpointApplicationRoleConnectionMetadata(appID)
+ var body []byte
+ body, err = s.RequestWithBucketID("GET", endpoint, nil, endpoint)
+ if err != nil {
+ return
+ }
+
+ err = unmarshal(body, &st)
+ return
+}
+
+// ApplicationRoleConnectionMetadataUpdate updates and returns application role connection metadata.
+// appID : ID of the application
+// metadata : New metadata
+func (s *Session) ApplicationRoleConnectionMetadataUpdate(appID string, metadata []*ApplicationRoleConnectionMetadata) (st []*ApplicationRoleConnectionMetadata, err error) {
+ endpoint := EndpointApplicationRoleConnectionMetadata(appID)
+ var body []byte
+ body, err = s.RequestWithBucketID("PUT", endpoint, metadata, endpoint)
+ if err != nil {
+ return
+ }
+
+ err = unmarshal(body, &st)
+ return
+}
+
+// UserApplicationRoleConnection returns user role connection to the specified application.
+// appID : ID of the application
+func (s *Session) UserApplicationRoleConnection(appID string) (st *ApplicationRoleConnection, err error) {
+ endpoint := EndpointUserApplicationRoleConnection(appID)
+ var body []byte
+ body, err = s.RequestWithBucketID("GET", endpoint, nil, endpoint)
+ if err != nil {
+ return
+ }
+
+ err = unmarshal(body, &st)
+ return
+
+}
+
+// UserApplicationRoleConnectionUpdate updates and returns user role connection to the specified application.
+// appID : ID of the application
+// connection : New ApplicationRoleConnection data
+func (s *Session) UserApplicationRoleConnectionUpdate(appID string, rconn *ApplicationRoleConnection) (st *ApplicationRoleConnection, err error) {
+ endpoint := EndpointUserApplicationRoleConnection(appID)
+ var body []byte
+ body, err = s.RequestWithBucketID("PUT", endpoint, rconn, endpoint)
+ if err != nil {
+ return
+ }
+
+ err = unmarshal(body, &st)
return
}
diff --git a/vendor/github.com/bwmarrin/discordgo/state.go b/vendor/github.com/bwmarrin/discordgo/state.go
index 6404b71d..d0c7b422 100644
--- a/vendor/github.com/bwmarrin/discordgo/state.go
+++ b/vendor/github.com/bwmarrin/discordgo/state.go
@@ -207,6 +207,15 @@ func (s *State) presenceAdd(guildID string, presence *Presence) error {
if presence.Status != "" {
guild.Presences[i].Status = presence.Status
}
+ if presence.ClientStatus.Desktop != "" {
+ guild.Presences[i].ClientStatus.Desktop = presence.ClientStatus.Desktop
+ }
+ if presence.ClientStatus.Mobile != "" {
+ guild.Presences[i].ClientStatus.Mobile = presence.ClientStatus.Mobile
+ }
+ if presence.ClientStatus.Web != "" {
+ guild.Presences[i].ClientStatus.Web = presence.ClientStatus.Web
+ }
//Update the optionally sent user information
//ID Is a mandatory field so you should not need to check if it is empty
@@ -909,9 +918,11 @@ func (s *State) onReady(se *Session, r *Ready) (err error) {
// if state is disabled, store the bare essentials.
if !se.StateEnabled {
ready := Ready{
- Version: r.Version,
- SessionID: r.SessionID,
- User: r.User,
+ Version: r.Version,
+ SessionID: r.SessionID,
+ User: r.User,
+ Shard: r.Shard,
+ Application: r.Application,
}
s.Ready = ready
@@ -981,6 +992,13 @@ func (s *State) OnInterface(se *Session, i interface{}) (err error) {
}
case *GuildMemberUpdate:
if s.TrackMembers {
+ var old *Member
+ old, err = s.Member(t.GuildID, t.User.ID)
+ if err == nil {
+ oldCopy := *old
+ t.BeforeUpdate = &oldCopy
+ }
+
err = s.MemberAdd(t.Member)
}
case *GuildMemberRemove:
@@ -1023,7 +1041,14 @@ func (s *State) OnInterface(se *Session, i interface{}) (err error) {
}
case *GuildEmojisUpdate:
if s.TrackEmojis {
- err = s.EmojisAdd(t.GuildID, t.Emojis)
+ var guild *Guild
+ guild, err = s.Guild(t.GuildID)
+ if err != nil {
+ return err
+ }
+ s.Lock()
+ defer s.Unlock()
+ guild.Emojis = t.Emojis
}
case *ChannelCreate:
if s.TrackChannels {
diff --git a/vendor/github.com/bwmarrin/discordgo/structs.go b/vendor/github.com/bwmarrin/discordgo/structs.go
index 26f507a9..1c29a7e9 100644
--- a/vendor/github.com/bwmarrin/discordgo/structs.go
+++ b/vendor/github.com/bwmarrin/discordgo/structs.go
@@ -17,7 +17,6 @@ import (
"math"
"net/http"
"regexp"
- "strings"
"sync"
"time"
@@ -156,6 +155,38 @@ type Application struct {
Flags int `json:"flags,omitempty"`
}
+// ApplicationRoleConnectionMetadataType represents the type of application role connection metadata.
+type ApplicationRoleConnectionMetadataType int
+
+// Application role connection metadata types.
+const (
+ ApplicationRoleConnectionMetadataIntegerLessThanOrEqual ApplicationRoleConnectionMetadataType = 1
+ ApplicationRoleConnectionMetadataIntegerGreaterThanOrEqual ApplicationRoleConnectionMetadataType = 2
+ ApplicationRoleConnectionMetadataIntegerEqual ApplicationRoleConnectionMetadataType = 3
+ ApplicationRoleConnectionMetadataIntegerNotEqual ApplicationRoleConnectionMetadataType = 4
+ ApplicationRoleConnectionMetadataDatetimeLessThanOrEqual ApplicationRoleConnectionMetadataType = 5
+ ApplicationRoleConnectionMetadataDatetimeGreaterThanOrEqual ApplicationRoleConnectionMetadataType = 6
+ ApplicationRoleConnectionMetadataBooleanEqual ApplicationRoleConnectionMetadataType = 7
+ ApplicationRoleConnectionMetadataBooleanNotEqual ApplicationRoleConnectionMetadataType = 8
+)
+
+// ApplicationRoleConnectionMetadata stores application role connection metadata.
+type ApplicationRoleConnectionMetadata struct {
+ Type ApplicationRoleConnectionMetadataType `json:"type"`
+ Key string `json:"key"`
+ Name string `json:"name"`
+ NameLocalizations map[Locale]string `json:"name_localizations"`
+ Description string `json:"description"`
+ DescriptionLocalizations map[Locale]string `json:"description_localizations"`
+}
+
+// ApplicationRoleConnection represents the role connection that an application has attached to a user.
+type ApplicationRoleConnection struct {
+ PlatformName string `json:"platform_name"`
+ PlatformUsername string `json:"platform_username"`
+ Metadata map[string]string `json:"metadata"`
+}
+
// UserConnection is a Connection returned from the UserConnections endpoint
type UserConnection struct {
ID string `json:"id"`
@@ -254,6 +285,42 @@ const (
ChannelTypeGuildPublicThread ChannelType = 11
ChannelTypeGuildPrivateThread ChannelType = 12
ChannelTypeGuildStageVoice ChannelType = 13
+ ChannelTypeGuildForum ChannelType = 15
+)
+
+// ChannelFlags represent flags of a channel/thread.
+type ChannelFlags int
+
+// Block containing known ChannelFlags values.
+const (
+ // ChannelFlagPinned indicates whether the thread is pinned in the forum channel.
+ // NOTE: forum threads only.
+ ChannelFlagPinned ChannelFlags = 1 << 1
+ // ChannelFlagRequireTag indicates whether a tag is required to be specified when creating a thread.
+ // NOTE: forum channels only.
+ ChannelFlagRequireTag ChannelFlags = 1 << 4
+)
+
+// ForumSortOrderType represents sort order of a forum channel.
+type ForumSortOrderType int
+
+const (
+ // ForumSortOrderLatestActivity sorts posts by activity.
+ ForumSortOrderLatestActivity ForumSortOrderType = 0
+ // ForumSortOrderCreationDate sorts posts by creation time (from most recent to oldest).
+ ForumSortOrderCreationDate ForumSortOrderType = 1
+)
+
+// ForumLayout represents layout of a forum channel.
+type ForumLayout int
+
+const (
+ // ForumLayoutNotSet represents no default layout.
+ ForumLayoutNotSet ForumLayout = 0
+ // ForumLayoutListView displays forum posts as a list.
+ ForumLayoutListView ForumLayout = 1
+ // ForumLayoutGalleryView displays forum posts as a collection of tiles.
+ ForumLayoutGalleryView ForumLayout = 2
)
// A Channel holds all data related to an individual Discord channel.
@@ -332,6 +399,30 @@ type Channel struct {
// All thread members. State channels only.
Members []*ThreadMember `json:"-"`
+
+ // Channel flags.
+ Flags ChannelFlags `json:"flags"`
+
+ // The set of tags that can be used in a forum channel.
+ AvailableTags []ForumTag `json:"available_tags"`
+
+ // The IDs of the set of tags that have been applied to a thread in a forum channel.
+ AppliedTags []string `json:"applied_tags"`
+
+ // Emoji to use as the default reaction to a forum post.
+ DefaultReactionEmoji ForumDefaultReaction `json:"default_reaction_emoji"`
+
+ // The initial RateLimitPerUser to set on newly created threads in a channel.
+ // This field is copied to the thread at creation time and does not live update.
+ DefaultThreadRateLimitPerUser int `json:"default_thread_rate_limit_per_user"`
+
+ // The default sort order type used to order posts in forum channels.
+ // Defaults to null, which indicates a preferred sort order hasn't been set by a channel admin.
+ DefaultSortOrder *ForumSortOrderType `json:"default_sort_order"`
+
+ // The default forum layout view used to display posts in forum channels.
+ // Defaults to ForumLayoutNotSet, which indicates a layout view has not been set by a channel admin.
+ DefaultForumLayout ForumLayout `json:"default_forum_layout"`
}
// Mention returns a string which mentions the channel
@@ -346,15 +437,17 @@ func (c *Channel) IsThread() bool {
// A ChannelEdit holds Channel Field data for a channel edit.
type ChannelEdit struct {
- Name string `json:"name,omitempty"`
- Topic string `json:"topic,omitempty"`
- NSFW *bool `json:"nsfw,omitempty"`
- Position int `json:"position"`
- Bitrate int `json:"bitrate,omitempty"`
- UserLimit int `json:"user_limit,omitempty"`
- PermissionOverwrites []*PermissionOverwrite `json:"permission_overwrites,omitempty"`
- ParentID string `json:"parent_id,omitempty"`
- RateLimitPerUser *int `json:"rate_limit_per_user,omitempty"`
+ Name string `json:"name,omitempty"`
+ Topic string `json:"topic,omitempty"`
+ NSFW *bool `json:"nsfw,omitempty"`
+ Position int `json:"position"`
+ Bitrate int `json:"bitrate,omitempty"`
+ UserLimit int `json:"user_limit,omitempty"`
+ PermissionOverwrites []*PermissionOverwrite `json:"permission_overwrites,omitempty"`
+ ParentID string `json:"parent_id,omitempty"`
+ RateLimitPerUser *int `json:"rate_limit_per_user,omitempty"`
+ Flags *ChannelFlags `json:"flags,omitempty"`
+ DefaultThreadRateLimitPerUser *int `json:"default_thread_rate_limit_per_user,omitempty"`
// NOTE: threads only
@@ -362,6 +455,16 @@ type ChannelEdit struct {
AutoArchiveDuration int `json:"auto_archive_duration,omitempty"`
Locked *bool `json:"locked,omitempty"`
Invitable *bool `json:"invitable,omitempty"`
+
+ // NOTE: forum channels only
+
+ AvailableTags *[]ForumTag `json:"available_tags,omitempty"`
+ DefaultReactionEmoji *ForumDefaultReaction `json:"default_reaction_emoji,omitempty"`
+ DefaultSortOrder *ForumSortOrderType `json:"default_sort_order,omitempty"` // TODO: null
+ DefaultForumLayout *ForumLayout `json:"default_forum_layout,omitempty"`
+
+ // NOTE: forum threads only
+ AppliedTags *[]string `json:"applied_tags,omitempty"`
}
// A ChannelFollow holds data returned after following a news channel
@@ -395,6 +498,9 @@ type ThreadStart struct {
Type ChannelType `json:"type,omitempty"`
Invitable bool `json:"invitable"`
RateLimitPerUser int `json:"rate_limit_per_user,omitempty"`
+
+ // NOTE: forum threads only
+ AppliedTags []string `json:"applied_tags,omitempty"`
}
// ThreadMetadata contains a number of thread-specific channel fields that are not needed by other channel types.
@@ -438,6 +544,24 @@ type AddedThreadMember struct {
Presence *Presence `json:"presence"`
}
+// ForumDefaultReaction specifies emoji to use as the default reaction to a forum post.
+// NOTE: Exactly one of EmojiID and EmojiName must be set.
+type ForumDefaultReaction struct {
+ // The id of a guild's custom emoji.
+ EmojiID string `json:"emoji_id,omitempty"`
+ // The unicode character of the emoji.
+ EmojiName string `json:"emoji_name,omitempty"`
+}
+
+// ForumTag represents a tag that is able to be applied to a thread in a forum channel.
+type ForumTag struct {
+ ID string `json:"id,omitempty"`
+ Name string `json:"name"`
+ Moderated bool `json:"moderated"`
+ EmojiID string `json:"emoji_id,omitempty"`
+ EmojiName string `json:"emoji_name,omitempty"`
+}
+
// Emoji struct holds data related to Emoji's
type Emoji struct {
ID string `json:"id"`
@@ -452,7 +576,7 @@ type Emoji struct {
// EmojiRegex is the regex used to find and identify emojis in messages
var (
- EmojiRegex = regexp.MustCompile(`<(a|):[A-z0-9_~]+:[0-9]{18}>`)
+ EmojiRegex = regexp.MustCompile(`<(a|):[A-z0-9_~]+:[0-9]{18,20}>`)
)
// MessageFormat returns a correctly formatted Emoji for use in Message content and embeds
@@ -792,16 +916,11 @@ type GuildPreview struct {
}
// IconURL returns a URL to the guild's icon.
-func (g *GuildPreview) IconURL() string {
- if g.Icon == "" {
- return ""
- }
-
- if strings.HasPrefix(g.Icon, "a_") {
- return EndpointGuildIconAnimated(g.ID, g.Icon)
- }
-
- return EndpointGuildIcon(g.ID, g.Icon)
+//
+// size: The size of the desired icon image as a power of two
+// Image size can be any power of two between 16 and 4096.
+func (g *GuildPreview) IconURL(size string) string {
+ return iconURL(g.Icon, EndpointGuildIcon(g.ID, g.Icon), EndpointGuildIconAnimated(g.ID, g.Icon), size)
}
// GuildScheduledEvent is a representation of a scheduled event in a guild. Only for retrieval of the data.
@@ -917,13 +1036,13 @@ type GuildScheduledEventStatus int
const (
// GuildScheduledEventStatusScheduled represents the current event is in scheduled state
- GuildScheduledEventStatusScheduled = 1
+ GuildScheduledEventStatusScheduled GuildScheduledEventStatus = 1
// GuildScheduledEventStatusActive represents the current event is in active state
- GuildScheduledEventStatusActive = 2
+ GuildScheduledEventStatusActive GuildScheduledEventStatus = 2
// GuildScheduledEventStatusCompleted represents the current event is in completed state
- GuildScheduledEventStatusCompleted = 3
+ GuildScheduledEventStatusCompleted GuildScheduledEventStatus = 3
// GuildScheduledEventStatusCanceled represents the current event is in canceled state
- GuildScheduledEventStatusCanceled = 4
+ GuildScheduledEventStatusCanceled GuildScheduledEventStatus = 4
)
// GuildScheduledEventEntityType is the type of entity associated with a guild scheduled event.
@@ -932,11 +1051,11 @@ type GuildScheduledEventEntityType int
const (
// GuildScheduledEventEntityTypeStageInstance represents a stage channel
- GuildScheduledEventEntityTypeStageInstance = 1
+ GuildScheduledEventEntityTypeStageInstance GuildScheduledEventEntityType = 1
// GuildScheduledEventEntityTypeVoice represents a voice channel
- GuildScheduledEventEntityTypeVoice = 2
+ GuildScheduledEventEntityTypeVoice GuildScheduledEventEntityType = 2
// GuildScheduledEventEntityTypeExternal represents an external event
- GuildScheduledEventEntityTypeExternal = 3
+ GuildScheduledEventEntityTypeExternal GuildScheduledEventEntityType = 3
)
// GuildScheduledEventUser is a user subscribed to a scheduled event.
@@ -1007,29 +1126,26 @@ type SystemChannelFlag int
// Block containing known SystemChannelFlag values
const (
- SystemChannelFlagsSuppressJoin SystemChannelFlag = 1 << 0
- SystemChannelFlagsSuppressPremium SystemChannelFlag = 1 << 1
+ SystemChannelFlagsSuppressJoinNotifications SystemChannelFlag = 1 << 0
+ SystemChannelFlagsSuppressPremium SystemChannelFlag = 1 << 1
+ SystemChannelFlagsSuppressGuildReminderNotifications SystemChannelFlag = 1 << 2
+ SystemChannelFlagsSuppressJoinNotificationReplies SystemChannelFlag = 1 << 3
)
// IconURL returns a URL to the guild's icon.
-func (g *Guild) IconURL() string {
- if g.Icon == "" {
- return ""
- }
-
- if strings.HasPrefix(g.Icon, "a_") {
- return EndpointGuildIconAnimated(g.ID, g.Icon)
- }
-
- return EndpointGuildIcon(g.ID, g.Icon)
+//
+// size: The size of the desired icon image as a power of two
+// Image size can be any power of two between 16 and 4096.
+func (g *Guild) IconURL(size string) string {
+ return iconURL(g.Icon, EndpointGuildIcon(g.ID, g.Icon), EndpointGuildIconAnimated(g.ID, g.Icon), size)
}
// BannerURL returns a URL to the guild's banner.
-func (g *Guild) BannerURL() string {
- if g.Banner == "" {
- return ""
- }
- return EndpointGuildBanner(g.ID, g.Banner)
+//
+// size: The size of the desired banner image as a power of two
+// Image size can be any power of two between 16 and 4096.
+func (g *Guild) BannerURL(size string) string {
+ return bannerURL(g.Banner, EndpointGuildBanner(g.ID, g.Banner), EndpointGuildBannerAnimated(g.ID, g.Banner), size)
}
// A UserGuild holds a brief version of a Guild
@@ -1076,12 +1192,22 @@ type GuildParams struct {
Region string `json:"region,omitempty"`
VerificationLevel *VerificationLevel `json:"verification_level,omitempty"`
DefaultMessageNotifications int `json:"default_message_notifications,omitempty"` // TODO: Separate type?
+ ExplicitContentFilter int `json:"explicit_content_filter,omitempty"`
AfkChannelID string `json:"afk_channel_id,omitempty"`
AfkTimeout int `json:"afk_timeout,omitempty"`
Icon string `json:"icon,omitempty"`
OwnerID string `json:"owner_id,omitempty"`
Splash string `json:"splash,omitempty"`
+ DiscoverySplash string `json:"discovery_splash,omitempty"`
Banner string `json:"banner,omitempty"`
+ SystemChannelID string `json:"system_channel_id,omitempty"`
+ SystemChannelFlags SystemChannelFlag `json:"system_channel_flags,omitempty"`
+ RulesChannelID string `json:"rules_channel_id,omitempty"`
+ PublicUpdatesChannelID string `json:"public_updates_channel_id,omitempty"`
+ PreferredLocale Locale `json:"preferred_locale,omitempty"`
+ Features []GuildFeature `json:"features,omitempty"`
+ Description string `json:"description,omitempty"`
+ PremiumProgressBarEnabled *bool `json:"premium_progress_bar_enabled,omitempty"`
}
// A Role stores information about Discord guild member roles.
@@ -1167,10 +1293,11 @@ type VoiceState struct {
// A Presence stores the online, offline, or idle and game status of Guild members.
type Presence struct {
- User *User `json:"user"`
- Status Status `json:"status"`
- Activities []*Activity `json:"activities"`
- Since *int `json:"since"`
+ User *User `json:"user"`
+ Status Status `json:"status"`
+ Activities []*Activity `json:"activities"`
+ Since *int `json:"since"`
+ ClientStatus ClientStatus `json:"client_status"`
}
// A TimeStamps struct contains start and end times used in the rich presence "playing .." Game
@@ -1249,9 +1376,10 @@ func (m *Member) Mention() string {
}
// AvatarURL returns the URL of the member's avatar
-// size: The size of the user's avatar as a power of two
-// if size is an empty string, no size parameter will
-// be added to the URL.
+//
+// size: The size of the user's avatar as a power of two
+// if size is an empty string, no size parameter will
+// be added to the URL.
func (m *Member) AvatarURL(size string) string {
if m.Avatar == "" {
return m.User.AvatarURL(size)
@@ -1262,6 +1390,13 @@ func (m *Member) AvatarURL(size string) string {
}
+// ClientStatus stores the online, offline, idle, or dnd status of each device of a Guild member.
+type ClientStatus struct {
+ Desktop Status `json:"desktop"`
+ Mobile Status `json:"mobile"`
+ Web Status `json:"web"`
+}
+
// Status type definition
type Status string
@@ -1371,9 +1506,21 @@ type AutoModerationTriggerMetadata struct {
// Substrings which will be searched for in content.
// NOTE: should be only used with keyword trigger type.
KeywordFilter []string `json:"keyword_filter,omitempty"`
+ // Regular expression patterns which will be matched against content (maximum of 10).
+ // NOTE: should be only used with keyword trigger type.
+ RegexPatterns []string `json:"regex_patterns,omitempty"`
+
// Internally pre-defined wordsets which will be searched for in content.
// NOTE: should be only used with keyword preset trigger type.
Presets []AutoModerationKeywordPreset `json:"presets,omitempty"`
+
+ // Substrings which should not trigger the rule.
+ // NOTE: should be only used with keyword or keyword preset trigger type.
+ AllowList *[]string `json:"allow_list,omitempty"`
+
+ // Total number of unique role and user mentions allowed per message.
+ // NOTE: should be only used with mention spam trigger type.
+ MentionTotalLimit int `json:"mention_total_limit,omitempty"`
}
// AutoModerationActionType represents an action which will execute whenever a rule is triggered.
@@ -2074,6 +2221,7 @@ const (
ErrCodeUnknownGuildWelcomeScreen = 10069
ErrCodeUnknownGuildScheduledEvent = 10070
ErrCodeUnknownGuildScheduledEventUser = 10071
+ ErrUnknownTag = 10087
ErrCodeBotsCannotUseEndpoint = 20001
ErrCodeOnlyBotsCanUseEndpoint = 20002
@@ -2087,28 +2235,30 @@ const (
ErrCodeStageTopicContainsNotAllowedWordsForPublicStages = 20031
ErrCodeGuildPremiumSubscriptionLevelTooLow = 20035
- ErrCodeMaximumGuildsReached = 30001
- ErrCodeMaximumPinsReached = 30003
- ErrCodeMaximumNumberOfRecipientsReached = 30004
- ErrCodeMaximumGuildRolesReached = 30005
- ErrCodeMaximumNumberOfWebhooksReached = 30007
- ErrCodeMaximumNumberOfEmojisReached = 30008
- ErrCodeTooManyReactions = 30010
- ErrCodeMaximumNumberOfGuildChannelsReached = 30013
- ErrCodeMaximumNumberOfAttachmentsInAMessageReached = 30015
- ErrCodeMaximumNumberOfInvitesReached = 30016
- ErrCodeMaximumNumberOfAnimatedEmojisReached = 30018
- ErrCodeMaximumNumberOfServerMembersReached = 30019
- ErrCodeMaximumNumberOfGuildDiscoverySubcategoriesReached = 30030
- ErrCodeGuildAlreadyHasATemplate = 30031
- ErrCodeMaximumNumberOfThreadParticipantsReached = 30033
- ErrCodeMaximumNumberOfBansForNonGuildMembersHaveBeenExceeded = 30035
- ErrCodeMaximumNumberOfBansFetchesHasBeenReached = 30037
- ErrCodeMaximumNumberOfUncompletedGuildScheduledEventsReached = 30038
- ErrCodeMaximumNumberOfStickersReached = 30039
- ErrCodeMaximumNumberOfPruneRequestsHasBeenReached = 30040
- ErrCodeMaximumNumberOfGuildWidgetSettingsUpdatesHasBeenReached = 30042
- ErrCodeMaximumNumberOfEditsToMessagesOlderThanOneHourReached = 30046
+ ErrCodeMaximumGuildsReached = 30001
+ ErrCodeMaximumPinsReached = 30003
+ ErrCodeMaximumNumberOfRecipientsReached = 30004
+ ErrCodeMaximumGuildRolesReached = 30005
+ ErrCodeMaximumNumberOfWebhooksReached = 30007
+ ErrCodeMaximumNumberOfEmojisReached = 30008
+ ErrCodeTooManyReactions = 30010
+ ErrCodeMaximumNumberOfGuildChannelsReached = 30013
+ ErrCodeMaximumNumberOfAttachmentsInAMessageReached = 30015
+ ErrCodeMaximumNumberOfInvitesReached = 30016
+ ErrCodeMaximumNumberOfAnimatedEmojisReached = 30018
+ ErrCodeMaximumNumberOfServerMembersReached = 30019
+ ErrCodeMaximumNumberOfGuildDiscoverySubcategoriesReached = 30030
+ ErrCodeGuildAlreadyHasATemplate = 30031
+ ErrCodeMaximumNumberOfThreadParticipantsReached = 30033
+ ErrCodeMaximumNumberOfBansForNonGuildMembersHaveBeenExceeded = 30035
+ ErrCodeMaximumNumberOfBansFetchesHasBeenReached = 30037
+ ErrCodeMaximumNumberOfUncompletedGuildScheduledEventsReached = 30038
+ ErrCodeMaximumNumberOfStickersReached = 30039
+ ErrCodeMaximumNumberOfPruneRequestsHasBeenReached = 30040
+ ErrCodeMaximumNumberOfGuildWidgetSettingsUpdatesHasBeenReached = 30042
+ ErrCodeMaximumNumberOfEditsToMessagesOlderThanOneHourReached = 30046
+ ErrCodeMaximumNumberOfPinnedThreadsInForumChannelHasBeenReached = 30047
+ ErrCodeMaximumNumberOfTagsInForumChannelHasBeenReached = 30048
ErrCodeUnauthorized = 40001
ErrCodeActionRequiredVerifiedAccount = 40002
@@ -2121,6 +2271,7 @@ const (
ErrCodeMessageAlreadyCrossposted = 40033
ErrCodeAnApplicationWithThatNameAlreadyExists = 40041
ErrCodeInteractionHasAlreadyBeenAcknowledged = 40060
+ ErrCodeTagNamesMustBeUnique = 40061
ErrCodeMissingAccess = 50001
ErrCodeInvalidAccountType = 50002
diff --git a/vendor/github.com/bwmarrin/discordgo/util.go b/vendor/github.com/bwmarrin/discordgo/util.go
index 86f43b5f..957f3018 100644
--- a/vendor/github.com/bwmarrin/discordgo/util.go
+++ b/vendor/github.com/bwmarrin/discordgo/util.go
@@ -51,7 +51,7 @@ func MultipartBodyWithJSON(data interface{}, files []*File) (requestContentType
for i, file := range files {
h := make(textproto.MIMEHeader)
- h.Set("Content-Disposition", fmt.Sprintf(`form-data; name="file%d"; filename="%s"`, i, quoteEscaper.Replace(file.Name)))
+ h.Set("Content-Disposition", fmt.Sprintf(`form-data; name="files[%d]"; filename="%s"`, i, quoteEscaper.Replace(file.Name)))
contentType := file.ContentType
if contentType == "" {
contentType = "application/octet-stream"
@@ -107,3 +107,19 @@ func bannerURL(bannerHash, staticBannerURL, animatedBannerURL, size string) stri
}
return URL
}
+
+func iconURL(iconHash, staticIconURL, animatedIconURL, size string) string {
+ var URL string
+ if iconHash == "" {
+ return ""
+ } else if strings.HasPrefix(iconHash, "a_") {
+ URL = animatedIconURL
+ } else {
+ URL = staticIconURL
+ }
+
+ if size != "" {
+ return URL + "?size=" + size
+ }
+ return URL
+}
diff --git a/vendor/github.com/bwmarrin/discordgo/voice.go b/vendor/github.com/bwmarrin/discordgo/voice.go
index efd88090..87e84b12 100644
--- a/vendor/github.com/bwmarrin/discordgo/voice.go
+++ b/vendor/github.com/bwmarrin/discordgo/voice.go
@@ -360,6 +360,25 @@ func (v *VoiceConnection) wsListen(wsConn *websocket.Conn, close <-chan struct{}
v.wsConn = nil
v.Unlock()
+ // Wait for VOICE_SERVER_UPDATE.
+ // When the bot is moved by the user to another voice channel,
+ // VOICE_SERVER_UPDATE is received after the code 4014.
+ for i := 0; i < 5; i++ { // TODO: temp, wait for VoiceServerUpdate.
+ <-time.After(1 * time.Second)
+
+ v.RLock()
+ reconnected := v.wsConn != nil
+ v.RUnlock()
+ if !reconnected {
+ continue
+ }
+ v.log(LogInformational, "successfully reconnected after 4014 manual disconnection")
+ return
+ }
+
+ // When VOICE_SERVER_UPDATE is not received, disconnect as usual.
+ v.log(LogInformational, "disconnect due to 4014 manual disconnection")
+
v.session.Lock()
delete(v.session.VoiceConnections, v.GuildID)
v.session.Unlock()
@@ -835,7 +854,7 @@ func (v *VoiceConnection) opusReceiver(udpConn *net.UDPConn, close <-chan struct
if opus, ok := secretbox.Open(nil, recvbuf[12:rlen], &nonce, &v.op4.SecretKey); ok {
p.Opus = opus
} else {
- return
+ continue
}
// extension bit set, and not a RTCP packet
diff --git a/vendor/github.com/bwmarrin/discordgo/wsapi.go b/vendor/github.com/bwmarrin/discordgo/wsapi.go
index 2579ee42..6c823884 100644
--- a/vendor/github.com/bwmarrin/discordgo/wsapi.go
+++ b/vendor/github.com/bwmarrin/discordgo/wsapi.go
@@ -320,7 +320,7 @@ func (s *Session) heartbeat(wsConn *websocket.Conn, listening <-chan interface{}
}
}
-// UpdateStatusData ia provided to UpdateStatusComplex()
+// UpdateStatusData is provided to UpdateStatusComplex()
type UpdateStatusData struct {
IdleSince *int `json:"since"`
Activities []*Activity `json:"activities"`
@@ -361,6 +361,14 @@ func (s *Session) UpdateGameStatus(idle int, name string) (err error) {
return s.UpdateStatusComplex(*newUpdateStatusData(idle, ActivityTypeGame, name, ""))
}
+// UpdateWatchStatus is used to update the user's watch status.
+// If idle>0 then set status to idle.
+// If name!="" then set movie/stream.
+// if otherwise, set status to active, and no activity.
+func (s *Session) UpdateWatchStatus(idle int, name string) (err error) {
+ return s.UpdateStatusComplex(*newUpdateStatusData(idle, ActivityTypeWatching, name, ""))
+}
+
// UpdateStreamingStatus is used to update the user's streaming status.
// If idle>0 then set status to idle.
// If name!="" then set game.
diff --git a/vendor/github.com/hashicorp/golang-lru/.golangci.yml b/vendor/github.com/hashicorp/golang-lru/.golangci.yml
new file mode 100644
index 00000000..49202fc4
--- /dev/null
+++ b/vendor/github.com/hashicorp/golang-lru/.golangci.yml
@@ -0,0 +1,30 @@
+linters:
+ enable:
+ - megacheck
+ - revive
+ - govet
+ - unconvert
+ - megacheck
+ - gas
+ - gocyclo
+ - dupl
+ - misspell
+ - unparam
+ - unused
+ - typecheck
+ - ineffassign
+ - stylecheck
+ - exportloopref
+ - gocritic
+ - nakedret
+ - gosimple
+ - prealloc
+ fast: false
+ disable-all: true
+
+issues:
+ exclude-rules:
+ - path: _test\.go
+ linters:
+ - dupl
+ exclude-use-default: false
diff --git a/vendor/github.com/hashicorp/golang-lru/2q.go b/vendor/github.com/hashicorp/golang-lru/2q.go
index e474cd07..15fcad03 100644
--- a/vendor/github.com/hashicorp/golang-lru/2q.go
+++ b/vendor/github.com/hashicorp/golang-lru/2q.go
@@ -44,7 +44,7 @@ func New2Q(size int) (*TwoQueueCache, error) {
// New2QParams creates a new TwoQueueCache using the provided
// parameter values.
-func New2QParams(size int, recentRatio float64, ghostRatio float64) (*TwoQueueCache, error) {
+func New2QParams(size int, recentRatio, ghostRatio float64) (*TwoQueueCache, error) {
if size <= 0 {
return nil, fmt.Errorf("invalid size")
}
@@ -138,7 +138,6 @@ func (c *TwoQueueCache) Add(key, value interface{}) {
// Add to the recently seen list
c.ensureSpace(false)
c.recent.Add(key, value)
- return
}
// ensureSpace is used to ensure we have space in the cache
diff --git a/vendor/github.com/hashicorp/golang-lru/LICENSE b/vendor/github.com/hashicorp/golang-lru/LICENSE
index be2cc4df..0e5d580e 100644
--- a/vendor/github.com/hashicorp/golang-lru/LICENSE
+++ b/vendor/github.com/hashicorp/golang-lru/LICENSE
@@ -1,3 +1,5 @@
+Copyright (c) 2014 HashiCorp, Inc.
+
Mozilla Public License, version 2.0
1. Definitions
diff --git a/vendor/github.com/hashicorp/golang-lru/README.md b/vendor/github.com/hashicorp/golang-lru/README.md
index 33e58cfa..063bb160 100644
--- a/vendor/github.com/hashicorp/golang-lru/README.md
+++ b/vendor/github.com/hashicorp/golang-lru/README.md
@@ -7,7 +7,7 @@ thread safe LRU cache. It is based on the cache in Groupcache.
Documentation
=============
-Full docs are available on [Godoc](http://godoc.org/github.com/hashicorp/golang-lru)
+Full docs are available on [Godoc](https://pkg.go.dev/github.com/hashicorp/golang-lru)
Example
=======
diff --git a/vendor/github.com/hashicorp/golang-lru/arc.go b/vendor/github.com/hashicorp/golang-lru/arc.go
index 555225a2..e396f842 100644
--- a/vendor/github.com/hashicorp/golang-lru/arc.go
+++ b/vendor/github.com/hashicorp/golang-lru/arc.go
@@ -173,7 +173,6 @@ func (c *ARCCache) Add(key, value interface{}) {
// Add to the recently seen list
c.t1.Add(key, value)
- return
}
// replace is used to adaptively evict from either T1 or T2
diff --git a/vendor/github.com/hashicorp/golang-lru/lru.go b/vendor/github.com/hashicorp/golang-lru/lru.go
index 4e5e9d8f..895d8e3e 100644
--- a/vendor/github.com/hashicorp/golang-lru/lru.go
+++ b/vendor/github.com/hashicorp/golang-lru/lru.go
@@ -6,10 +6,17 @@ import (
"github.com/hashicorp/golang-lru/simplelru"
)
+const (
+ // DefaultEvictedBufferSize defines the default buffer size to store evicted key/val
+ DefaultEvictedBufferSize = 16
+)
+
// Cache is a thread-safe fixed size LRU cache.
type Cache struct {
- lru simplelru.LRUCache
- lock sync.RWMutex
+ lru *simplelru.LRU
+ evictedKeys, evictedVals []interface{}
+ onEvictedCB func(k, v interface{})
+ lock sync.RWMutex
}
// New creates an LRU of the given size.
@@ -19,30 +26,63 @@ func New(size int) (*Cache, error) {
// NewWithEvict constructs a fixed size cache with the given eviction
// callback.
-func NewWithEvict(size int, onEvicted func(key interface{}, value interface{})) (*Cache, error) {
- lru, err := simplelru.NewLRU(size, simplelru.EvictCallback(onEvicted))
- if err != nil {
- return nil, err
+func NewWithEvict(size int, onEvicted func(key, value interface{})) (c *Cache, err error) {
+ // create a cache with default settings
+ c = &Cache{
+ onEvictedCB: onEvicted,
}
- c := &Cache{
- lru: lru,
+ if onEvicted != nil {
+ c.initEvictBuffers()
+ onEvicted = c.onEvicted
}
- return c, nil
+ c.lru, err = simplelru.NewLRU(size, onEvicted)
+ return
+}
+
+func (c *Cache) initEvictBuffers() {
+ c.evictedKeys = make([]interface{}, 0, DefaultEvictedBufferSize)
+ c.evictedVals = make([]interface{}, 0, DefaultEvictedBufferSize)
+}
+
+// onEvicted save evicted key/val and sent in externally registered callback
+// outside of critical section
+func (c *Cache) onEvicted(k, v interface{}) {
+ c.evictedKeys = append(c.evictedKeys, k)
+ c.evictedVals = append(c.evictedVals, v)
}
// Purge is used to completely clear the cache.
func (c *Cache) Purge() {
+ var ks, vs []interface{}
c.lock.Lock()
c.lru.Purge()
+ if c.onEvictedCB != nil && len(c.evictedKeys) > 0 {
+ ks, vs = c.evictedKeys, c.evictedVals
+ c.initEvictBuffers()
+ }
c.lock.Unlock()
+ // invoke callback outside of critical section
+ if c.onEvictedCB != nil {
+ for i := 0; i < len(ks); i++ {
+ c.onEvictedCB(ks[i], vs[i])
+ }
+ }
}
// Add adds a value to the cache. Returns true if an eviction occurred.
func (c *Cache) Add(key, value interface{}) (evicted bool) {
+ var k, v interface{}
c.lock.Lock()
evicted = c.lru.Add(key, value)
+ if c.onEvictedCB != nil && evicted {
+ k, v = c.evictedKeys[0], c.evictedVals[0]
+ c.evictedKeys, c.evictedVals = c.evictedKeys[:0], c.evictedVals[:0]
+ }
c.lock.Unlock()
- return evicted
+ if c.onEvictedCB != nil && evicted {
+ c.onEvictedCB(k, v)
+ }
+ return
}
// Get looks up a key's value from the cache.
@@ -75,13 +115,21 @@ func (c *Cache) Peek(key interface{}) (value interface{}, ok bool) {
// recent-ness or deleting it for being stale, and if not, adds the value.
// Returns whether found and whether an eviction occurred.
func (c *Cache) ContainsOrAdd(key, value interface{}) (ok, evicted bool) {
+ var k, v interface{}
c.lock.Lock()
- defer c.lock.Unlock()
-
if c.lru.Contains(key) {
+ c.lock.Unlock()
return true, false
}
evicted = c.lru.Add(key, value)
+ if c.onEvictedCB != nil && evicted {
+ k, v = c.evictedKeys[0], c.evictedVals[0]
+ c.evictedKeys, c.evictedVals = c.evictedKeys[:0], c.evictedVals[:0]
+ }
+ c.lock.Unlock()
+ if c.onEvictedCB != nil && evicted {
+ c.onEvictedCB(k, v)
+ }
return false, evicted
}
@@ -89,47 +137,80 @@ func (c *Cache) ContainsOrAdd(key, value interface{}) (ok, evicted bool) {
// recent-ness or deleting it for being stale, and if not, adds the value.
// Returns whether found and whether an eviction occurred.
func (c *Cache) PeekOrAdd(key, value interface{}) (previous interface{}, ok, evicted bool) {
+ var k, v interface{}
c.lock.Lock()
- defer c.lock.Unlock()
-
previous, ok = c.lru.Peek(key)
if ok {
+ c.lock.Unlock()
return previous, true, false
}
-
evicted = c.lru.Add(key, value)
+ if c.onEvictedCB != nil && evicted {
+ k, v = c.evictedKeys[0], c.evictedVals[0]
+ c.evictedKeys, c.evictedVals = c.evictedKeys[:0], c.evictedVals[:0]
+ }
+ c.lock.Unlock()
+ if c.onEvictedCB != nil && evicted {
+ c.onEvictedCB(k, v)
+ }
return nil, false, evicted
}
// Remove removes the provided key from the cache.
func (c *Cache) Remove(key interface{}) (present bool) {
+ var k, v interface{}
c.lock.Lock()
present = c.lru.Remove(key)
+ if c.onEvictedCB != nil && present {
+ k, v = c.evictedKeys[0], c.evictedVals[0]
+ c.evictedKeys, c.evictedVals = c.evictedKeys[:0], c.evictedVals[:0]
+ }
c.lock.Unlock()
+ if c.onEvictedCB != nil && present {
+ c.onEvictedCB(k, v)
+ }
return
}
// Resize changes the cache size.
func (c *Cache) Resize(size int) (evicted int) {
+ var ks, vs []interface{}
c.lock.Lock()
evicted = c.lru.Resize(size)
+ if c.onEvictedCB != nil && evicted > 0 {
+ ks, vs = c.evictedKeys, c.evictedVals
+ c.initEvictBuffers()
+ }
c.lock.Unlock()
+ if c.onEvictedCB != nil && evicted > 0 {
+ for i := 0; i < len(ks); i++ {
+ c.onEvictedCB(ks[i], vs[i])
+ }
+ }
return evicted
}
// RemoveOldest removes the oldest item from the cache.
-func (c *Cache) RemoveOldest() (key interface{}, value interface{}, ok bool) {
+func (c *Cache) RemoveOldest() (key, value interface{}, ok bool) {
+ var k, v interface{}
c.lock.Lock()
key, value, ok = c.lru.RemoveOldest()
+ if c.onEvictedCB != nil && ok {
+ k, v = c.evictedKeys[0], c.evictedVals[0]
+ c.evictedKeys, c.evictedVals = c.evictedKeys[:0], c.evictedVals[:0]
+ }
c.lock.Unlock()
+ if c.onEvictedCB != nil && ok {
+ c.onEvictedCB(k, v)
+ }
return
}
// GetOldest returns the oldest entry
-func (c *Cache) GetOldest() (key interface{}, value interface{}, ok bool) {
- c.lock.Lock()
+func (c *Cache) GetOldest() (key, value interface{}, ok bool) {
+ c.lock.RLock()
key, value, ok = c.lru.GetOldest()
- c.lock.Unlock()
+ c.lock.RUnlock()
return
}
diff --git a/vendor/github.com/hashicorp/golang-lru/simplelru/lru.go b/vendor/github.com/hashicorp/golang-lru/simplelru/lru.go
index a86c8539..9233583c 100644
--- a/vendor/github.com/hashicorp/golang-lru/simplelru/lru.go
+++ b/vendor/github.com/hashicorp/golang-lru/simplelru/lru.go
@@ -25,7 +25,7 @@ type entry struct {
// NewLRU constructs an LRU of the given size
func NewLRU(size int, onEvict EvictCallback) (*LRU, error) {
if size <= 0 {
- return nil, errors.New("Must provide a positive size")
+ return nil, errors.New("must provide a positive size")
}
c := &LRU{
size: size,
@@ -109,7 +109,7 @@ func (c *LRU) Remove(key interface{}) (present bool) {
}
// RemoveOldest removes the oldest item from the cache.
-func (c *LRU) RemoveOldest() (key interface{}, value interface{}, ok bool) {
+func (c *LRU) RemoveOldest() (key, value interface{}, ok bool) {
ent := c.evictList.Back()
if ent != nil {
c.removeElement(ent)
@@ -120,7 +120,7 @@ func (c *LRU) RemoveOldest() (key interface{}, value interface{}, ok bool) {
}
// GetOldest returns the oldest entry
-func (c *LRU) GetOldest() (key interface{}, value interface{}, ok bool) {
+func (c *LRU) GetOldest() (key, value interface{}, ok bool) {
ent := c.evictList.Back()
if ent != nil {
kv := ent.Value.(*entry)
diff --git a/vendor/github.com/hashicorp/golang-lru/simplelru/lru_interface.go b/vendor/github.com/hashicorp/golang-lru/simplelru/lru_interface.go
index 92d70934..cb7f8caf 100644
--- a/vendor/github.com/hashicorp/golang-lru/simplelru/lru_interface.go
+++ b/vendor/github.com/hashicorp/golang-lru/simplelru/lru_interface.go
@@ -1,3 +1,4 @@
+// Package simplelru provides simple LRU implementation based on build-in container/list.
package simplelru
// LRUCache is the interface for simple LRU cache.
@@ -34,6 +35,6 @@ type LRUCache interface {
// Clears all cache entries.
Purge()
- // Resizes cache, returning number evicted
- Resize(int) int
+ // Resizes cache, returning number evicted
+ Resize(int) int
}
diff --git a/vendor/github.com/hashicorp/golang-lru/testing.go b/vendor/github.com/hashicorp/golang-lru/testing.go
new file mode 100644
index 00000000..49276078
--- /dev/null
+++ b/vendor/github.com/hashicorp/golang-lru/testing.go
@@ -0,0 +1,16 @@
+package lru
+
+import (
+ "crypto/rand"
+ "math"
+ "math/big"
+ "testing"
+)
+
+func getRand(tb testing.TB) int64 {
+ out, err := rand.Int(rand.Reader, big.NewInt(math.MaxInt64))
+ if err != nil {
+ tb.Fatal(err)
+ }
+ return out.Int64()
+}
diff --git a/vendor/github.com/keybase/go-keybase-chat-bot/kbchat/chat.go b/vendor/github.com/keybase/go-keybase-chat-bot/kbchat/chat.go
index 129c43fa..bb2d26b8 100644
--- a/vendor/github.com/keybase/go-keybase-chat-bot/kbchat/chat.go
+++ b/vendor/github.com/keybase/go-keybase-chat-bot/kbchat/chat.go
@@ -122,7 +122,8 @@ func (a *API) GetTextMessages(channel chat1.ChatChannel, unreadOnly bool) ([]cha
return res, nil
}
-func (a *API) SendMessage(channel chat1.ChatChannel, body string, args ...interface{}) (SendResponse, error) {
+func (a *API) SendMessage(channel chat1.ChatChannel, body string, args ...interface{}) (resp SendResponse, err error) {
+ defer a.Trace(&err, "SendMessage")()
arg := newSendArg(sendMessageOptions{
Channel: channel,
Message: sendMessageBody{
@@ -139,7 +140,8 @@ func (a *API) Broadcast(body string, args ...interface{}) (SendResponse, error)
}, fmt.Sprintf(body, args...))
}
-func (a *API) SendMessageByConvID(convID chat1.ConvIDStr, body string, args ...interface{}) (SendResponse, error) {
+func (a *API) SendMessageByConvID(convID chat1.ConvIDStr, body string, args ...interface{}) (resp SendResponse, err error) {
+ defer a.Trace(&err, "SendMessageByConvID")()
arg := newSendArg(sendMessageOptions{
ConversationID: convID,
Message: sendMessageBody{
@@ -150,7 +152,8 @@ func (a *API) SendMessageByConvID(convID chat1.ConvIDStr, body string, args ...i
}
// SendMessageByTlfName sends a message on the given TLF name
-func (a *API) SendMessageByTlfName(tlfName string, body string, args ...interface{}) (SendResponse, error) {
+func (a *API) SendMessageByTlfName(tlfName string, body string, args ...interface{}) (resp SendResponse, err error) {
+ defer a.Trace(&err, "SendMessageByTlfName")()
arg := newSendArg(sendMessageOptions{
Channel: chat1.ChatChannel{
Name: tlfName,
@@ -162,7 +165,8 @@ func (a *API) SendMessageByTlfName(tlfName string, body string, args ...interfac
return a.doSend(arg)
}
-func (a *API) SendMessageByTeamName(teamName string, inChannel *string, body string, args ...interface{}) (SendResponse, error) {
+func (a *API) SendMessageByTeamName(teamName string, inChannel *string, body string, args ...interface{}) (resp SendResponse, err error) {
+ defer a.Trace(&err, "SendMessageByTeamName")()
channel := "general"
if inChannel != nil {
channel = *inChannel
diff --git a/vendor/github.com/keybase/go-keybase-chat-bot/kbchat/kbchat.go b/vendor/github.com/keybase/go-keybase-chat-bot/kbchat/kbchat.go
index b8d9eb3c..b5248106 100644
--- a/vendor/github.com/keybase/go-keybase-chat-bot/kbchat/kbchat.go
+++ b/vendor/github.com/keybase/go-keybase-chat-bot/kbchat/kbchat.go
@@ -6,6 +6,7 @@ import (
"errors"
"fmt"
"io"
+ "math"
"os"
"os/exec"
"runtime"
@@ -45,10 +46,10 @@ type Subscription struct {
}
func NewSubscription() *Subscription {
- newMsgsCh := make(chan SubscriptionMessage, 100)
- newConvsCh := make(chan SubscriptionConversation, 100)
- newWalletCh := make(chan SubscriptionWalletEvent, 100)
- errorCh := make(chan error, 100)
+ newMsgsCh := make(chan SubscriptionMessage, 250)
+ newConvsCh := make(chan SubscriptionConversation, 250)
+ newWalletCh := make(chan SubscriptionWalletEvent, 250)
+ errorCh := make(chan error, 250)
shutdownCh := make(chan struct{})
return &Subscription{
DebugOutput: NewDebugOutput("Subscription"),
@@ -137,6 +138,8 @@ type RunOptions struct {
EnableTyping bool
// Disable bot lite mode
DisableBotLiteMode bool
+ // Number of processes to spin up to connect to the keybase service
+ NumPipes int
}
func (r RunOptions) Location() string {
@@ -164,13 +167,20 @@ func Start(runOpts RunOptions, opts ...func(*API)) (*API, error) {
return api, nil
}
+type apiPipe struct {
+ sync.Mutex
+ input io.Writer
+ output *bufio.Reader
+ cmd *exec.Cmd
+}
+
// API is the main object used for communicating with the Keybase JSON API
type API struct {
sync.Mutex
*DebugOutput
- apiInput io.Writer
- apiOutput *bufio.Reader
- apiCmd *exec.Cmd
+ // Round robin hand out API pipes to allow concurrent API requests.
+ pipeIdx int
+ pipes []*apiPipe
username string
runOpts RunOptions
subscriptions []*Subscription
@@ -282,12 +292,15 @@ func (a *API) auth() (string, error) {
func (a *API) startPipes() (err error) {
a.Lock()
defer a.Unlock()
- if a.apiCmd != nil {
- if err := a.apiCmd.Process.Kill(); err != nil {
- return fmt.Errorf("unable to kill previous API command %v", err)
+ for _, pipe := range a.pipes {
+ if pipe.cmd != nil {
+ if err := pipe.cmd.Process.Kill(); err != nil {
+ return fmt.Errorf("unable to kill previous API command %v", err)
+ }
}
+ pipe.cmd = nil
}
- a.apiCmd = nil
+ a.pipes = nil
if a.runOpts.StartService {
args := []string{fmt.Sprintf("-enable-bot-lite-mode=%v", a.runOpts.DisableBotLiteMode), "service"}
@@ -306,30 +319,39 @@ func (a *API) startPipes() (err error) {
a.Debug("unable to set notifiation settings %v", err)
}
- a.apiCmd = a.runOpts.Command("chat", "api")
- if a.apiInput, err = a.apiCmd.StdinPipe(); err != nil {
- return fmt.Errorf("unable to get api stdin: %v", err)
- }
- output, err := a.apiCmd.StdoutPipe()
- if err != nil {
- return fmt.Errorf("unable to get api stdout: %v", err)
- }
- if runtime.GOOS != "windows" {
- a.apiCmd.ExtraFiles = []*os.File{output.(*os.File)}
- }
- if err := a.apiCmd.Start(); err != nil {
- return fmt.Errorf("unable to run chat api cmd: %v", err)
+ // Startup NumPipes processes to the keybase chat api
+ for i := 0; i < int(math.Max(float64(a.runOpts.NumPipes), 1)); i++ {
+ pipe := apiPipe{}
+ pipe.cmd = a.runOpts.Command("chat", "api")
+ if pipe.input, err = pipe.cmd.StdinPipe(); err != nil {
+ return fmt.Errorf("unable to get api stdin: %v", err)
+ }
+ output, err := pipe.cmd.StdoutPipe()
+ if err != nil {
+ return fmt.Errorf("unable to get api stdout: %v", err)
+ }
+ if runtime.GOOS != "windows" {
+ pipe.cmd.ExtraFiles = []*os.File{output.(*os.File)}
+ }
+ if err := pipe.cmd.Start(); err != nil {
+ return fmt.Errorf("unable to run chat api cmd: %v", err)
+ }
+ pipe.output = bufio.NewReader(output)
+ a.pipes = append(a.pipes, &pipe)
}
- a.apiOutput = bufio.NewReader(output)
return nil
}
-func (a *API) getAPIPipesLocked() (io.Writer, *bufio.Reader, error) {
- // this should only be called inside a lock
- if a.apiCmd == nil {
- return nil, nil, errAPIDisconnected
+func (a *API) getAPIPipes() (*apiPipe, error) {
+ a.Lock()
+ defer a.Unlock()
+ idx := a.pipeIdx % len(a.pipes)
+ a.pipeIdx++
+ pipe := a.pipes[idx]
+ if pipe.cmd == nil {
+ return nil, errAPIDisconnected
}
- return a.apiInput, a.apiOutput, nil
+ return pipe, nil
}
func (a *API) GetUsername() string {
@@ -337,21 +359,21 @@ func (a *API) GetUsername() string {
}
func (a *API) doSend(arg interface{}) (resp SendResponse, err error) {
- a.Lock()
- defer a.Unlock()
-
bArg, err := json.Marshal(arg)
if err != nil {
return SendResponse{}, fmt.Errorf("unable to send arg: %+v: %v", arg, err)
}
- input, output, err := a.getAPIPipesLocked()
+ pipe, err := a.getAPIPipes()
if err != nil {
return SendResponse{}, err
}
- if _, err := io.WriteString(input, string(bArg)); err != nil {
+ pipe.Lock()
+ defer pipe.Unlock()
+
+ if _, err := io.WriteString(pipe.input, string(bArg)); err != nil {
return SendResponse{}, err
}
- responseRaw, err := output.ReadBytes('\n')
+ responseRaw, err := pipe.output.ReadBytes('\n')
if err != nil {
return SendResponse{}, err
}
@@ -364,17 +386,17 @@ func (a *API) doSend(arg interface{}) (resp SendResponse, err error) {
}
func (a *API) doFetch(apiInput string) ([]byte, error) {
- a.Lock()
- defer a.Unlock()
-
- input, output, err := a.getAPIPipesLocked()
+ pipe, err := a.getAPIPipes()
if err != nil {
return nil, err
}
- if _, err := io.WriteString(input, apiInput); err != nil {
+ pipe.Lock()
+ defer pipe.Unlock()
+
+ if _, err := io.WriteString(pipe.input, apiInput); err != nil {
return nil, err
}
- byteOutput, err := output.ReadBytes('\n')
+ byteOutput, err := pipe.output.ReadBytes('\n')
if err != nil {
return nil, err
}
@@ -412,16 +434,22 @@ func (a *API) Listen(opts ListenOptions) (*Subscription, error) {
}
boutput.Scan()
t := boutput.Text()
+ submitErr := func(err error) {
+ if len(sub.errorCh)*2 > cap(sub.errorCh) {
+ a.Debug("large errorCh queue: len: %d cap: %d ", len(sub.errorCh), cap(sub.errorCh))
+ }
+ sub.errorCh <- err
+ }
var typeHolder TypeHolder
if err := json.Unmarshal([]byte(t), &typeHolder); err != nil {
- sub.errorCh <- fmt.Errorf("err: %v, data: %v", err, t)
+ submitErr(fmt.Errorf("err: %v, data: %v", err, t))
break
}
switch typeHolder.Type {
case "chat":
var notification chat1.MsgNotification
if err := json.Unmarshal([]byte(t), &notification); err != nil {
- sub.errorCh <- fmt.Errorf("err: %v, data: %v", err, t)
+ submitErr(fmt.Errorf("err: %v, data: %v", err, t))
break
}
if notification.Error != nil {
@@ -434,12 +462,15 @@ func (a *API) Listen(opts ListenOptions) (*Subscription, error) {
Channel: notification.Msg.Channel,
},
}
+ if len(sub.newMsgsCh)*2 > cap(sub.newMsgsCh) {
+ a.Debug("large newMsgsCh queue: len: %d cap: %d ", len(sub.newMsgsCh), cap(sub.newMsgsCh))
+ }
sub.newMsgsCh <- subscriptionMessage
}
case "chat_conv":
var notification chat1.ConvNotification
if err := json.Unmarshal([]byte(t), &notification); err != nil {
- sub.errorCh <- fmt.Errorf("err: %v, data: %v", err, t)
+ submitErr(fmt.Errorf("err: %v, data: %v", err, t))
break
}
if notification.Error != nil {
@@ -448,15 +479,21 @@ func (a *API) Listen(opts ListenOptions) (*Subscription, error) {
subscriptionConv := SubscriptionConversation{
Conversation: *notification.Conv,
}
+ if len(sub.newConvsCh)*2 > cap(sub.newConvsCh) {
+ a.Debug("large newConvsCh queue: len: %d cap: %d ", len(sub.newConvsCh), cap(sub.newConvsCh))
+ }
sub.newConvsCh <- subscriptionConv
}
case "wallet":
var holder PaymentHolder
if err := json.Unmarshal([]byte(t), &holder); err != nil {
- sub.errorCh <- fmt.Errorf("err: %v, data: %v", err, t)
+ submitErr(fmt.Errorf("err: %v, data: %v", err, t))
break
}
subscriptionPayment := SubscriptionWalletEvent(holder)
+ if len(sub.newWalletCh)*2 > cap(sub.newWalletCh) {
+ a.Debug("large newWalletCh queue: len: %d cap: %d ", len(sub.newWalletCh), cap(sub.newWalletCh))
+ }
sub.newWalletCh <- subscriptionPayment
default:
continue
@@ -518,7 +555,6 @@ func (a *API) Listen(opts ListenOptions) (*Subscription, error) {
}
boutput := bufio.NewScanner(output)
if err := p.Start(); err != nil {
-
a.Debug("Listen: failed to make listen scanner: %s", err)
time.Sleep(pause)
continue
@@ -568,10 +604,12 @@ func (a *API) Shutdown() (err error) {
for _, sub := range a.subscriptions {
sub.Shutdown()
}
- if a.apiCmd != nil {
- a.Debug("waiting for API command")
- if err := a.apiCmd.Wait(); err != nil {
- return err
+ for _, pipe := range a.pipes {
+ if pipe.cmd != nil {
+ a.Debug("waiting for API command")
+ if err := pipe.cmd.Wait(); err != nil {
+ return err
+ }
}
}
diff --git a/vendor/github.com/kyokomi/emoji/v2/README.md b/vendor/github.com/kyokomi/emoji/v2/README.md
index e6045985..7cf9ba57 100644
--- a/vendor/github.com/kyokomi/emoji/v2/README.md
+++ b/vendor/github.com/kyokomi/emoji/v2/README.md
@@ -1,7 +1,7 @@
# Emoji
Emoji is a simple golang package.
-[![wercker status](https://app.wercker.com/status/7bef60de2c6d3e0e6c13d56b2393c5d8/s/master "wercker status")](https://app.wercker.com/project/byKey/7bef60de2c6d3e0e6c13d56b2393c5d8)
+![master workflow](https://github.com/kyokomi/emoji/actions/workflows/go.yml/badge.svg)
[![Coverage Status](https://coveralls.io/repos/kyokomi/emoji/badge.png?branch=master)](https://coveralls.io/r/kyokomi/emoji?branch=master)
[![GoDoc](https://pkg.go.dev/badge/github.com/kyokomi/emoji.svg)](https://pkg.go.dev/github.com/kyokomi/emoji/v2)
diff --git a/vendor/github.com/kyokomi/emoji/v2/emoji_codemap.go b/vendor/github.com/kyokomi/emoji/v2/emoji_codemap.go
index 278b711c..c44cb618 100644
--- a/vendor/github.com/kyokomi/emoji/v2/emoji_codemap.go
+++ b/vendor/github.com/kyokomi/emoji/v2/emoji_codemap.go
@@ -84,6 +84,7 @@ func emojiCode() map[string]string {
":UP!_button:": "\U0001f199",
":VS_button:": "\U0001f19a",
":Virgo:": "\u264d",
+ ":ZZZ:": "\U0001f4a4",
":a:": "\U0001f170\ufe0f",
":ab:": "\U0001f18e",
":abacus:": "\U0001f9ee",
@@ -298,6 +299,7 @@ func emojiCode() map[string]string {
":birthday_cake:": "\U0001f382",
":bison:": "\U0001f9ac",
":biting_lip:": "\U0001fae6",
+ ":black_bird:": "\U0001f426\u200d\u2b1b",
":black_cat:": "\U0001f408\u200d\u2b1b",
":black_circle:": "\u26ab",
":black_circle_for_record:": "\u23fa\ufe0f",
@@ -779,6 +781,7 @@ func emojiCode() map[string]string {
":dolphin:": "\U0001f42c",
":dominica:": "\U0001f1e9\U0001f1f2",
":dominican_republic:": "\U0001f1e9\U0001f1f4",
+ ":donkey:": "\U0001facf",
":door:": "\U0001f6aa",
":dotted_line_face:": "\U0001fae5",
":dotted_six-pointed_star:": "\U0001f52f",
@@ -850,6 +853,7 @@ func emojiCode() map[string]string {
":empty_nest:": "\U0001fab9",
":end:": "\U0001f51a",
":england:": "\U0001f3f4\U000e0067\U000e0062\U000e0065\U000e006e\U000e0067\U000e007f",
+ ":enraged_face:": "\U0001f621",
":envelope:": "\u2709",
":envelope_with_arrow:": "\U0001f4e9",
":equatorial_guinea:": "\U0001f1ec\U0001f1f6",
@@ -1837,12 +1841,14 @@ func emojiCode() map[string]string {
":flower_playing_cards:": "\U0001f3b4",
":flushed:": "\U0001f633",
":flushed_face:": "\U0001f633",
+ ":flute:": "\U0001fa88",
":fly:": "\U0001fab0",
":flying_disc:": "\U0001f94f",
":flying_saucer:": "\U0001f6f8",
":fog:": "\U0001f32b\ufe0f",
":foggy:": "\U0001f301",
":folded_hands:": "\U0001f64f",
+ ":folding_hand_fan:": "\U0001faad",
":fondue:": "\U0001fad5",
":foot:": "\U0001f9b6",
":football:": "\U0001f3c8",
@@ -1906,6 +1912,7 @@ func emojiCode() map[string]string {
":gibraltar:": "\U0001f1ec\U0001f1ee",
":gift:": "\U0001f381",
":gift_heart:": "\U0001f49d",
+ ":ginger_root:": "\U0001fada",
":giraffe:": "\U0001f992",
":giraffe_face:": "\U0001f992",
":girl:": "\U0001f467",
@@ -1932,6 +1939,7 @@ func emojiCode() map[string]string {
":golfing:": "\U0001f3cc\ufe0f",
":golfing_man:": "\U0001f3cc\ufe0f\u200d\u2642\ufe0f",
":golfing_woman:": "\U0001f3cc\ufe0f\u200d\u2640\ufe0f",
+ ":goose:": "\U0001fabf",
":gorilla:": "\U0001f98d",
":graduation_cap:": "\U0001f393",
":grapes:": "\U0001f347",
@@ -1945,6 +1953,7 @@ func emojiCode() map[string]string {
":greenland:": "\U0001f1ec\U0001f1f1",
":grenada:": "\U0001f1ec\U0001f1e9",
":grey_exclamation:": "\u2755",
+ ":grey_heart:": "\U0001fa76",
":grey_question:": "\u2754",
":grimacing:": "\U0001f62c",
":grimacing_face:": "\U0001f62c",
@@ -1976,6 +1985,7 @@ func emojiCode() map[string]string {
":guitar:": "\U0001f3b8",
":gun:": "\U0001f52b",
":guyana:": "\U0001f1ec\U0001f1fe",
+ ":hair_pick:": "\U0001faae",
":haircut:": "\U0001f487\u200d\u2640\ufe0f",
":haircut_man:": "\U0001f487\u200d\u2642\ufe0f",
":haircut_woman:": "\U0001f487\u200d\u2640\ufe0f",
@@ -2094,6 +2104,7 @@ func emojiCode() map[string]string {
":hushed:": "\U0001f62f",
":hushed_face:": "\U0001f62f",
":hut:": "\U0001f6d6",
+ ":hyacinth:": "\U0001fabb",
":i_love_you_hand_sign:": "\U0001f91f",
":ice:": "\U0001f9ca",
":ice_cream:": "\U0001f368",
@@ -2142,6 +2153,7 @@ func emojiCode() map[string]string {
":japanese_ogre:": "\U0001f479",
":jar:": "\U0001fad9",
":jeans:": "\U0001f456",
+ ":jellyfish:": "\U0001fabc",
":jersey:": "\U0001f1ef\U0001f1ea",
":jigsaw:": "\U0001f9e9",
":joker:": "\U0001f0cf",
@@ -2175,6 +2187,7 @@ func emojiCode() map[string]string {
":keycap_9:": "9\ufe0f\u20e3",
":keycap_star:": "*\ufe0f\u20e3",
":keycap_ten:": "\U0001f51f",
+ ":khanda:": "\U0001faaf",
":kick_scooter:": "\U0001f6f4",
":kimono:": "\U0001f458",
":kiribati:": "\U0001f1f0\U0001f1ee",
@@ -2261,6 +2274,7 @@ func emojiCode() map[string]string {
":left_speech_bubble:": "\U0001f5e8\ufe0f",
":leftwards_arrow_with_hook:": "\u21a9\ufe0f",
":leftwards_hand:": "\U0001faf2",
+ ":leftwards_pushing_hand:": "\U0001faf7",
":leg:": "\U0001f9b5",
":lemon:": "\U0001f34b",
":leo:": "\u264c",
@@ -2271,6 +2285,7 @@ func emojiCode() map[string]string {
":libra:": "\u264e",
":libya:": "\U0001f1f1\U0001f1fe",
":liechtenstein:": "\U0001f1f1\U0001f1ee",
+ ":light_blue_heart:": "\U0001fa75",
":light_bulb:": "\U0001f4a1",
":light_rail:": "\U0001f688",
":lightning:": "\U0001f329\ufe0f",
@@ -2807,6 +2822,7 @@ func emojiCode() map[string]string {
":map:": "\U0001f5fa",
":map_of_Japan:": "\U0001f5fe",
":maple_leaf:": "\U0001f341",
+ ":maracas:": "\U0001fa87",
":marshall_islands:": "\U0001f1f2\U0001f1ed",
":martial_arts_uniform:": "\U0001f94b",
":martinique:": "\U0001f1f2\U0001f1f6",
@@ -2911,6 +2927,7 @@ func emojiCode() map[string]string {
":moon:": "\U0001f314",
":moon_cake:": "\U0001f96e",
":moon_viewing_ceremony:": "\U0001f391",
+ ":moose:": "\U0001face",
":morocco:": "\U0001f1f2\U0001f1e6",
":mortar_board:": "\U0001f393",
":mosque:": "\U0001f54c",
@@ -3159,6 +3176,7 @@ func emojiCode() map[string]string {
":passport_control:": "\U0001f6c2",
":pause_button:": "\u23f8",
":paw_prints:": "\U0001f43e",
+ ":pea_pod:": "\U0001fadb",
":peace:": "\u262e",
":peace_symbol:": "\u262e\ufe0f",
":peach:": "\U0001f351",
@@ -3410,6 +3428,7 @@ func emojiCode() map[string]string {
":pine_decoration:": "\U0001f38d",
":pineapple:": "\U0001f34d",
":ping_pong:": "\U0001f3d3",
+ ":pink_heart:": "\U0001fa77",
":pirate_flag:": "\U0001f3f4\u200d\u2620\ufe0f",
":pisces:": "\u2653",
":pitcairn_islands:": "\U0001f1f5\U0001f1f3",
@@ -3486,7 +3505,7 @@ func emojiCode() map[string]string {
":pouring_liquid:": "\U0001fad7",
":pout:": "\U0001f621",
":pouting_cat:": "\U0001f63e",
- ":pouting_face:": "\U0001f621",
+ ":pouting_face:": "\U0001f64e",
":pouting_man:": "\U0001f64e\u200d\u2642\ufe0f",
":pouting_woman:": "\U0001f64e\u200d\u2640\ufe0f",
":pray:": "\U0001f64f",
@@ -3641,6 +3660,7 @@ func emojiCode() map[string]string {
":right_facing_fist_tone4:": "\U0001f91c\U0001f3fe",
":right_facing_fist_tone5:": "\U0001f91c\U0001f3ff",
":rightwards_hand:": "\U0001faf1",
+ ":rightwards_pushing_hand:": "\U0001faf8",
":ring:": "\U0001f48d",
":ring_buoy:": "\U0001f6df",
":ringed_planet:": "\U0001fa90",
@@ -3747,6 +3767,7 @@ func emojiCode() map[string]string {
":seven_o’clock:": "\U0001f556",
":sewing_needle:": "\U0001faa1",
":seychelles:": "\U0001f1f8\U0001f1e8",
+ ":shaking_face:": "\U0001fae8",
":shallow_pan_of_food:": "\U0001f958",
":shamrock:": "\u2618\ufe0f",
":shark:": "\U0001f988",
@@ -4275,9 +4296,11 @@ func emojiCode() map[string]string {
":wind_face:": "\U0001f32c",
":window:": "\U0001fa9f",
":wine_glass:": "\U0001f377",
+ ":wing:": "\U0001fabd",
":wink:": "\U0001f609",
":winking_face:": "\U0001f609",
":winking_face_with_tongue:": "\U0001f61c",
+ ":wireless:": "\U0001f6dc",
":wolf:": "\U0001f43a",
":woman:": "\U0001f469",
":woman-biking:": "\U0001f6b4\u200d\u2640\ufe0f",
@@ -4708,6 +4731,7 @@ func emojiCode() map[string]string {
":writing_hand_tone5:": "\u270d\U0001f3ff",
":x:": "\u274c",
":x-ray:": "\U0001fa7b",
+ ":x_ray:": "\U0001fa7b",
":yarn:": "\U0001f9f6",
":yawning_face:": "\U0001f971",
":yellow_circle:": "\U0001f7e1",
@@ -5470,6 +5494,7 @@ func emojiRevCode() map[string][]string {
"\U0001f424": {":baby_chick:"},
"\U0001f425": {":hatched_chick:", ":front-facing_baby_chick:"},
"\U0001f426": {":bird:"},
+ "\U0001f426\u200d\u2b1b": {":black_bird:"},
"\U0001f427": {":penguin:"},
"\U0001f428": {":koala:"},
"\U0001f429": {":poodle:"},
@@ -6104,7 +6129,7 @@ func emojiRevCode() map[string][]string {
"\U0001f4a1": {":bulb:", ":light_bulb:"},
"\U0001f4a2": {":anger:", ":anger_symbol:"},
"\U0001f4a3": {":bomb:"},
- "\U0001f4a4": {":zzz:"},
+ "\U0001f4a4": {":ZZZ:", ":zzz:"},
"\U0001f4a5": {":boom:", ":collision:"},
"\U0001f4a6": {":sweat_drops:", ":sweat_droplets:"},
"\U0001f4a7": {":droplet:"},
@@ -6438,7 +6463,7 @@ func emojiRevCode() map[string][]string {
"\U0001f61e": {":disappointed:", ":disappointed_face:"},
"\U0001f61f": {":worried:", ":worried_face:"},
"\U0001f620": {":angry:", ":angry_face:"},
- "\U0001f621": {":pout:", ":rage:", ":pouting_face:"},
+ "\U0001f621": {":pout:", ":rage:", ":enraged_face:"},
"\U0001f622": {":cry:", ":crying_face:"},
"\U0001f623": {":persevere:", ":persevering_face:"},
"\U0001f624": {":triumph:", ":face_with_steam_from_nose:"},
@@ -6576,7 +6601,7 @@ func emojiRevCode() map[string][]string {
"\U0001f64d\U0001f3ff\u200d\u2642\ufe0f": {":man_frowning_tone5:"},
"\U0001f64d\u200d\u2640\ufe0f": {":frowning_woman:", ":woman-frowning:", ":woman_frowning:", ":person_frowning:"},
"\U0001f64d\u200d\u2642\ufe0f": {":frowning_man:", ":man-frowning:", ":man_frowning:"},
- "\U0001f64e": {":person_pouting:"},
+ "\U0001f64e": {":pouting_face:", ":person_pouting:"},
"\U0001f64e\U0001f3fb": {":person_pouting_tone1:"},
"\U0001f64e\U0001f3fb\u200d\u2640\ufe0f": {":woman_pouting_tone1:"},
"\U0001f64e\U0001f3fb\u200d\u2642\ufe0f": {":man_pouting_tone1:"},
@@ -6761,6 +6786,7 @@ func emojiRevCode() map[string][]string {
"\U0001f6d5": {":hindu_temple:"},
"\U0001f6d6": {":hut:"},
"\U0001f6d7": {":elevator:"},
+ "\U0001f6dc": {":wireless:"},
"\U0001f6dd": {":playground_slide:"},
"\U0001f6de": {":wheel:"},
"\U0001f6df": {":ring_buoy:"},
@@ -7422,10 +7448,13 @@ func emojiRevCode() map[string][]string {
"\U0001fa72": {":briefs:", ":swim_brief:"},
"\U0001fa73": {":shorts:"},
"\U0001fa74": {":thong_sandal:"},
+ "\U0001fa75": {":light_blue_heart:"},
+ "\U0001fa76": {":grey_heart:"},
+ "\U0001fa77": {":pink_heart:"},
"\U0001fa78": {":drop_of_blood:"},
"\U0001fa79": {":adhesive_bandage:"},
"\U0001fa7a": {":stethoscope:"},
- "\U0001fa7b": {":x-ray:"},
+ "\U0001fa7b": {":x-ray:", ":x_ray:"},
"\U0001fa7c": {":crutch:"},
"\U0001fa80": {":yo-yo:", ":yo_yo:"},
"\U0001fa81": {":kite:"},
@@ -7434,6 +7463,8 @@ func emojiRevCode() map[string][]string {
"\U0001fa84": {":magic_wand:"},
"\U0001fa85": {":pinata:", ":piñata:"},
"\U0001fa86": {":nesting_dolls:"},
+ "\U0001fa87": {":maracas:"},
+ "\U0001fa88": {":flute:"},
"\U0001fa90": {":ringed_planet:"},
"\U0001fa91": {":chair:"},
"\U0001fa92": {":razor:"},
@@ -7463,6 +7494,9 @@ func emojiRevCode() map[string][]string {
"\U0001faaa": {":identification_card:"},
"\U0001faab": {":low_battery:"},
"\U0001faac": {":hamsa:"},
+ "\U0001faad": {":folding_hand_fan:"},
+ "\U0001faae": {":hair_pick:"},
+ "\U0001faaf": {":khanda:"},
"\U0001fab0": {":fly:"},
"\U0001fab1": {":worm:"},
"\U0001fab2": {":beetle:"},
@@ -7474,12 +7508,18 @@ func emojiRevCode() map[string][]string {
"\U0001fab8": {":coral:"},
"\U0001fab9": {":empty_nest:"},
"\U0001faba": {":nest_with_eggs:"},
+ "\U0001fabb": {":hyacinth:"},
+ "\U0001fabc": {":jellyfish:"},
+ "\U0001fabd": {":wing:"},
+ "\U0001fabf": {":goose:"},
"\U0001fac0": {":anatomical_heart:"},
"\U0001fac1": {":lungs:"},
"\U0001fac2": {":people_hugging:"},
"\U0001fac3": {":pregnant_man:"},
"\U0001fac4": {":pregnant_person:"},
"\U0001fac5": {":person_with_crown:"},
+ "\U0001face": {":moose:"},
+ "\U0001facf": {":donkey:"},
"\U0001fad0": {":blueberries:"},
"\U0001fad1": {":bell_pepper:"},
"\U0001fad2": {":olive:"},
@@ -7490,6 +7530,8 @@ func emojiRevCode() map[string][]string {
"\U0001fad7": {":pouring_liquid:"},
"\U0001fad8": {":beans:"},
"\U0001fad9": {":jar:"},
+ "\U0001fada": {":ginger_root:"},
+ "\U0001fadb": {":pea_pod:"},
"\U0001fae0": {":melting_face:"},
"\U0001fae1": {":saluting_face:"},
"\U0001fae2": {":face_with_open_eyes_and_hand_over_mouth:"},
@@ -7498,6 +7540,7 @@ func emojiRevCode() map[string][]string {
"\U0001fae5": {":dotted_line_face:"},
"\U0001fae6": {":biting_lip:"},
"\U0001fae7": {":bubbles:"},
+ "\U0001fae8": {":shaking_face:"},
"\U0001faf0": {":hand_with_index_finger_and_thumb_crossed:"},
"\U0001faf1": {":rightwards_hand:"},
"\U0001faf2": {":leftwards_hand:"},
@@ -7505,6 +7548,8 @@ func emojiRevCode() map[string][]string {
"\U0001faf4": {":palm_up_hand:"},
"\U0001faf5": {":index_pointing_at_the_viewer:"},
"\U0001faf6": {":heart_hands:"},
+ "\U0001faf7": {":leftwards_pushing_hand:"},
+ "\U0001faf8": {":rightwards_pushing_hand:"},
"\u00a9\ufe0f": {":copyright:"},
"\u00ae\ufe0f": {":registered:"},
"\u203c": {":double_exclamation_mark:"},
diff --git a/vendor/github.com/kyokomi/emoji/v2/wercker.yml b/vendor/github.com/kyokomi/emoji/v2/wercker.yml
deleted file mode 100644
index 82bd2099..00000000
--- a/vendor/github.com/kyokomi/emoji/v2/wercker.yml
+++ /dev/null
@@ -1,33 +0,0 @@
-box: golang
-build:
- steps:
- - setup-go-workspace
- - script:
- name: go version
- code: go version
- - script:
- name: install tools
- code: |
- go install github.com/mattn/goveralls@latest
- go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
- - script:
- name: go get
- code: |
- go get ./...
- - script:
- name: go build
- code: |
- go build ./...
- - script:
- name: golangci-lint
- code: |
- golangci-lint run
- - script:
- name: go test
- code: |
- go test ./...
- - script:
- name: coveralls
- code: |
- goveralls -v -service wercker.com -repotoken $COVERALLS_TOKEN
-
diff --git a/vendor/github.com/labstack/echo/v4/CHANGELOG.md b/vendor/github.com/labstack/echo/v4/CHANGELOG.md
index 8b71fb8e..c1c3c107 100644
--- a/vendor/github.com/labstack/echo/v4/CHANGELOG.md
+++ b/vendor/github.com/labstack/echo/v4/CHANGELOG.md
@@ -1,5 +1,42 @@
# Changelog
+## v4.10.0 - 2022-12-27
+
+**Security**
+
+* We are deprecating JWT middleware in this repository. Please use https://github.com/labstack/echo-jwt instead.
+
+ JWT middleware is moved to separate repository to allow us to bump/upgrade version of JWT implementation (`github.com/golang-jwt/jwt`) we are using
+which we can not do in Echo core because this would break backwards compatibility guarantees we try to maintain.
+
+* This minor version bumps minimum Go version to 1.17 (from 1.16) due `golang.org/x/` packages we depend on. There are
+ several vulnerabilities fixed in these libraries.
+
+ Echo still tries to support last 4 Go versions but there are occasions we can not guarantee this promise.
+
+
+**Enhancements**
+
+* Bump x/text to 0.3.8 [#2305](https://github.com/labstack/echo/pull/2305)
+* Bump dependencies and add notes about Go releases we support [#2336](https://github.com/labstack/echo/pull/2336)
+* Add helper interface for ProxyBalancer interface [#2316](https://github.com/labstack/echo/pull/2316)
+* Expose `middleware.CreateExtractors` function so we can use it from echo-contrib repository [#2338](https://github.com/labstack/echo/pull/2338)
+* Refactor func(Context) error to HandlerFunc [#2315](https://github.com/labstack/echo/pull/2315)
+* Improve function comments [#2329](https://github.com/labstack/echo/pull/2329)
+* Add new method HTTPError.WithInternal [#2340](https://github.com/labstack/echo/pull/2340)
+* Replace io/ioutil package usages [#2342](https://github.com/labstack/echo/pull/2342)
+* Add staticcheck to CI flow [#2343](https://github.com/labstack/echo/pull/2343)
+* Replace relative path determination from proprietary to std [#2345](https://github.com/labstack/echo/pull/2345)
+* Remove square brackets from ipv6 addresses in XFF (X-Forwarded-For header) [#2182](https://github.com/labstack/echo/pull/2182)
+* Add testcases for some BodyLimit middleware configuration options [#2350](https://github.com/labstack/echo/pull/2350)
+* Additional configuration options for RequestLogger and Logger middleware [#2341](https://github.com/labstack/echo/pull/2341)
+* Add route to request log [#2162](https://github.com/labstack/echo/pull/2162)
+* GitHub Workflows security hardening [#2358](https://github.com/labstack/echo/pull/2358)
+* Add govulncheck to CI and bump dependencies [#2362](https://github.com/labstack/echo/pull/2362)
+* Fix rate limiter docs [#2366](https://github.com/labstack/echo/pull/2366)
+* Refactor how `e.Routes()` work and introduce `e.OnAddRouteHandler` callback [#2337](https://github.com/labstack/echo/pull/2337)
+
+
## v4.9.1 - 2022-10-12
**Fixes**
diff --git a/vendor/github.com/labstack/echo/v4/Makefile b/vendor/github.com/labstack/echo/v4/Makefile
index a6c4aaa9..6aff6a89 100644
--- a/vendor/github.com/labstack/echo/v4/Makefile
+++ b/vendor/github.com/labstack/echo/v4/Makefile
@@ -10,8 +10,10 @@ check: lint vet race ## Check project
init:
@go install golang.org/x/lint/golint@latest
+ @go install honnef.co/go/tools/cmd/staticcheck@latest
lint: ## Lint the files
+ @staticcheck ${PKG_LIST}
@golint -set_exit_status ${PKG_LIST}
vet: ## Vet the files
@@ -29,6 +31,6 @@ benchmark: ## Run benchmarks
help: ## Display this help screen
@grep -h -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
-goversion ?= "1.16"
-test_version: ## Run tests inside Docker with given version (defaults to 1.15 oldest supported). Example: make test_version goversion=1.16
+goversion ?= "1.17"
+test_version: ## Run tests inside Docker with given version (defaults to 1.17 oldest supported). Example: make test_version goversion=1.17
@docker run --rm -it -v $(shell pwd):/project golang:$(goversion) /bin/sh -c "cd /project && make init check"
diff --git a/vendor/github.com/labstack/echo/v4/context.go b/vendor/github.com/labstack/echo/v4/context.go
index 5567100b..b3a7ce8d 100644
--- a/vendor/github.com/labstack/echo/v4/context.go
+++ b/vendor/github.com/labstack/echo/v4/context.go
@@ -169,7 +169,11 @@ type (
// Redirect redirects the request to a provided URL with status code.
Redirect(code int, url string) error
- // Error invokes the registered HTTP error handler. Generally used by middleware.
+ // Error invokes the registered global HTTP error handler. Generally used by middleware.
+ // A side-effect of calling global error handler is that now Response has been committed (sent to the client) and
+ // middlewares up in chain can not change Response status code or Response body anymore.
+ //
+ // Avoid using this method in handlers as no middleware will be able to effectively handle errors after that.
Error(err error)
// Handler returns the matched handler by router.
@@ -282,11 +286,16 @@ func (c *context) RealIP() string {
if ip := c.request.Header.Get(HeaderXForwardedFor); ip != "" {
i := strings.IndexAny(ip, ",")
if i > 0 {
- return strings.TrimSpace(ip[:i])
+ xffip := strings.TrimSpace(ip[:i])
+ xffip = strings.TrimPrefix(xffip, "[")
+ xffip = strings.TrimSuffix(xffip, "]")
+ return xffip
}
return ip
}
if ip := c.request.Header.Get(HeaderXRealIP); ip != "" {
+ ip = strings.TrimPrefix(ip, "[")
+ ip = strings.TrimSuffix(ip, "]")
return ip
}
ra, _, _ := net.SplitHostPort(c.request.RemoteAddr)
diff --git a/vendor/github.com/labstack/echo/v4/echo.go b/vendor/github.com/labstack/echo/v4/echo.go
index 5ae8a142..f6d89b96 100644
--- a/vendor/github.com/labstack/echo/v4/echo.go
+++ b/vendor/github.com/labstack/echo/v4/echo.go
@@ -3,50 +3,49 @@ Package echo implements high performance, minimalist Go web framework.
Example:
- package main
+ package main
- import (
- "net/http"
+ import (
+ "net/http"
- "github.com/labstack/echo/v4"
- "github.com/labstack/echo/v4/middleware"
- )
+ "github.com/labstack/echo/v4"
+ "github.com/labstack/echo/v4/middleware"
+ )
- // Handler
- func hello(c echo.Context) error {
- return c.String(http.StatusOK, "Hello, World!")
- }
+ // Handler
+ func hello(c echo.Context) error {
+ return c.String(http.StatusOK, "Hello, World!")
+ }
- func main() {
- // Echo instance
- e := echo.New()
+ func main() {
+ // Echo instance
+ e := echo.New()
- // Middleware
- e.Use(middleware.Logger())
- e.Use(middleware.Recover())
+ // Middleware
+ e.Use(middleware.Logger())
+ e.Use(middleware.Recover())
- // Routes
- e.GET("/", hello)
+ // Routes
+ e.GET("/", hello)
- // Start server
- e.Logger.Fatal(e.Start(":1323"))
- }
+ // Start server
+ e.Logger.Fatal(e.Start(":1323"))
+ }
Learn more at https://echo.labstack.com
*/
package echo
import (
- "bytes"
stdContext "context"
"crypto/tls"
"errors"
"fmt"
"io"
- "io/ioutil"
stdLog "log"
"net"
"net/http"
+ "os"
"reflect"
"runtime"
"sync"
@@ -62,20 +61,28 @@ import (
type (
// Echo is the top-level framework instance.
+ //
+ // Goroutine safety: Do not mutate Echo instance fields after server has started. Accessing these
+ // fields from handlers/middlewares and changing field values at the same time leads to data-races.
+ // Adding new routes after the server has been started is also not safe!
Echo struct {
filesystem
common
// startupMutex is mutex to lock Echo instance access during server configuration and startup. Useful for to get
// listener address info (on which interface/port was listener binded) without having data races.
- startupMutex sync.RWMutex
+ startupMutex sync.RWMutex
+ colorer *color.Color
+
+ // premiddleware are middlewares that are run before routing is done. In case a pre-middleware returns
+ // an error the router is not executed and the request will end up in the global error handler.
+ premiddleware []MiddlewareFunc
+ middleware []MiddlewareFunc
+ maxParam *int
+ router *Router
+ routers map[string]*Router
+ pool sync.Pool
+
StdLogger *stdLog.Logger
- colorer *color.Color
- premiddleware []MiddlewareFunc
- middleware []MiddlewareFunc
- maxParam *int
- router *Router
- routers map[string]*Router
- pool sync.Pool
Server *http.Server
TLSServer *http.Server
Listener net.Listener
@@ -93,6 +100,9 @@ type (
Logger Logger
IPExtractor IPExtractor
ListenerNetwork string
+
+ // OnAddRouteHandler is called when Echo adds new route to specific host router.
+ OnAddRouteHandler func(host string, route Route, handler HandlerFunc, middleware []MiddlewareFunc)
}
// Route contains a handler and information for matching against requests.
@@ -116,7 +126,7 @@ type (
HandlerFunc func(c Context) error
// HTTPErrorHandler is a centralized HTTP error handler.
- HTTPErrorHandler func(error, Context)
+ HTTPErrorHandler func(err error, c Context)
// Validator is the interface that wraps the Validate function.
Validator interface {
@@ -248,7 +258,7 @@ const (
const (
// Version of Echo
- Version = "4.9.0"
+ Version = "4.10.0"
website = "https://echo.labstack.com"
// http://patorjk.com/software/taag/#p=display&f=Small%20Slant&t=Echo
banner = `
@@ -527,21 +537,20 @@ func (e *Echo) File(path, file string, m ...MiddlewareFunc) *Route {
return e.file(path, file, e.GET, m...)
}
-func (e *Echo) add(host, method, path string, handler HandlerFunc, middleware ...MiddlewareFunc) *Route {
- name := handlerName(handler)
+func (e *Echo) add(host, method, path string, handler HandlerFunc, middlewares ...MiddlewareFunc) *Route {
router := e.findRouter(host)
- // FIXME: when handler+middleware are both nil ... make it behave like handler removal
- router.Add(method, path, func(c Context) error {
- h := applyMiddleware(handler, middleware...)
+ //FIXME: when handler+middleware are both nil ... make it behave like handler removal
+ name := handlerName(handler)
+ route := router.add(method, path, name, func(c Context) error {
+ h := applyMiddleware(handler, middlewares...)
return h(c)
})
- r := &Route{
- Method: method,
- Path: path,
- Name: name,
+
+ if e.OnAddRouteHandler != nil {
+ e.OnAddRouteHandler(host, *route, handler, middlewares)
}
- e.router.routes[method+path] = r
- return r
+
+ return route
}
// Add registers a new route for an HTTP method and path with matching handler
@@ -565,7 +574,7 @@ func (e *Echo) Group(prefix string, m ...MiddlewareFunc) (g *Group) {
return
}
-// URI generates a URI from handler.
+// URI generates an URI from handler.
func (e *Echo) URI(handler HandlerFunc, params ...interface{}) string {
name := handlerName(handler)
return e.Reverse(name, params...)
@@ -578,35 +587,13 @@ func (e *Echo) URL(h HandlerFunc, params ...interface{}) string {
// Reverse generates an URL from route name and provided parameters.
func (e *Echo) Reverse(name string, params ...interface{}) string {
- uri := new(bytes.Buffer)
- ln := len(params)
- n := 0
- for _, r := range e.router.routes {
- if r.Name == name {
- for i, l := 0, len(r.Path); i < l; i++ {
- if (r.Path[i] == ':' || r.Path[i] == '*') && n < ln {
- for ; i < l && r.Path[i] != '/'; i++ {
- }
- uri.WriteString(fmt.Sprintf("%v", params[n]))
- n++
- }
- if i < l {
- uri.WriteByte(r.Path[i])
- }
- }
- break
- }
- }
- return uri.String()
+ return e.router.Reverse(name, params...)
}
-// Routes returns the registered routes.
+// Routes returns the registered routes for default router.
+// In case when Echo serves multiple hosts/domains use `e.Routers()["domain2.site"].Routes()` to get specific host routes.
func (e *Echo) Routes() []*Route {
- routes := make([]*Route, 0, len(e.router.routes))
- for _, v := range e.router.routes {
- routes = append(routes, v)
- }
- return routes
+ return e.router.Routes()
}
// AcquireContext returns an empty `Context` instance from the pool.
@@ -626,7 +613,7 @@ func (e *Echo) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// Acquire context
c := e.pool.Get().(*context)
c.Reset(r, w)
- var h func(Context) error
+ var h HandlerFunc
if e.premiddleware == nil {
e.findRouter(r.Host).Find(r.Method, GetPath(r), c)
@@ -700,7 +687,7 @@ func (e *Echo) StartTLS(address string, certFile, keyFile interface{}) (err erro
func filepathOrContent(fileOrContent interface{}) (content []byte, err error) {
switch v := fileOrContent.(type) {
case string:
- return ioutil.ReadFile(v)
+ return os.ReadFile(v)
case []byte:
return v, nil
default:
@@ -884,6 +871,15 @@ func (he *HTTPError) SetInternal(err error) *HTTPError {
return he
}
+// WithInternal returns clone of HTTPError with err set to HTTPError.Internal field
+func (he *HTTPError) WithInternal(err error) *HTTPError {
+ return &HTTPError{
+ Code: he.Code,
+ Message: he.Message,
+ Internal: err,
+ }
+}
+
// Unwrap satisfies the Go 1.13 error wrapper interface.
func (he *HTTPError) Unwrap() error {
return he.Internal
@@ -913,8 +909,8 @@ func WrapMiddleware(m func(http.Handler) http.Handler) MiddlewareFunc {
// GetPath returns RawPath, if it's empty returns Path from URL
// Difference between RawPath and Path is:
-// * Path is where request path is stored. Value is stored in decoded form: /%47%6f%2f becomes /Go/.
-// * RawPath is an optional field which only gets set if the default encoding is different from Path.
+// - Path is where request path is stored. Value is stored in decoded form: /%47%6f%2f becomes /Go/.
+// - RawPath is an optional field which only gets set if the default encoding is different from Path.
func GetPath(r *http.Request) string {
path := r.URL.RawPath
if path == "" {
diff --git a/vendor/github.com/labstack/echo/v4/echo_fs.go b/vendor/github.com/labstack/echo/v4/echo_fs.go
index b8526da9..9f83a035 100644
--- a/vendor/github.com/labstack/echo/v4/echo_fs.go
+++ b/vendor/github.com/labstack/echo/v4/echo_fs.go
@@ -7,7 +7,6 @@ import (
"net/url"
"os"
"path/filepath"
- "runtime"
"strings"
)
@@ -125,7 +124,7 @@ func subFS(currentFs fs.FS, root string) (fs.FS, error) {
// we need to make exception for `defaultFS` instances as it interprets root prefix differently from fs.FS.
// fs.Fs.Open does not like relative paths ("./", "../") and absolute paths at all but prior echo.Filesystem we
// were able to use paths like `./myfile.log`, `/etc/hosts` and these would work fine with `os.Open` but not with fs.Fs
- if isRelativePath(root) {
+ if !filepath.IsAbs(root) {
root = filepath.Join(dFS.prefix, root)
}
return &defaultFS{
@@ -136,21 +135,6 @@ func subFS(currentFs fs.FS, root string) (fs.FS, error) {
return fs.Sub(currentFs, root)
}
-func isRelativePath(path string) bool {
- if path == "" {
- return true
- }
- if path[0] == '/' {
- return false
- }
- if runtime.GOOS == "windows" && strings.IndexByte(path, ':') != -1 {
- // https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file?redirectedfrom=MSDN#file_and_directory_names
- // https://docs.microsoft.com/en-us/dotnet/standard/io/file-path-formats
- return false
- }
- return true
-}
-
// MustSubFS creates sub FS from current filesystem or panic on failure.
// Panic happens when `fsRoot` contains invalid path according to `fs.ValidPath` rules.
//
diff --git a/vendor/github.com/labstack/echo/v4/ip.go b/vendor/github.com/labstack/echo/v4/ip.go
index 46d464cf..1bcd756a 100644
--- a/vendor/github.com/labstack/echo/v4/ip.go
+++ b/vendor/github.com/labstack/echo/v4/ip.go
@@ -227,6 +227,8 @@ func ExtractIPFromRealIPHeader(options ...TrustOption) IPExtractor {
return func(req *http.Request) string {
realIP := req.Header.Get(HeaderXRealIP)
if realIP != "" {
+ realIP = strings.TrimPrefix(realIP, "[")
+ realIP = strings.TrimSuffix(realIP, "]")
if ip := net.ParseIP(realIP); ip != nil && checker.trust(ip) {
return realIP
}
@@ -248,7 +250,10 @@ func ExtractIPFromXFFHeader(options ...TrustOption) IPExtractor {
}
ips := append(strings.Split(strings.Join(xffs, ","), ","), directIP)
for i := len(ips) - 1; i >= 0; i-- {
- ip := net.ParseIP(strings.TrimSpace(ips[i]))
+ ips[i] = strings.TrimSpace(ips[i])
+ ips[i] = strings.TrimPrefix(ips[i], "[")
+ ips[i] = strings.TrimSuffix(ips[i], "]")
+ ip := net.ParseIP(ips[i])
if ip == nil {
// Unable to parse IP; cannot trust entire records
return directIP
diff --git a/vendor/github.com/labstack/echo/v4/middleware/body_dump.go b/vendor/github.com/labstack/echo/v4/middleware/body_dump.go
index ebd0d0ab..fa7891b1 100644
--- a/vendor/github.com/labstack/echo/v4/middleware/body_dump.go
+++ b/vendor/github.com/labstack/echo/v4/middleware/body_dump.go
@@ -4,7 +4,6 @@ import (
"bufio"
"bytes"
"io"
- "io/ioutil"
"net"
"net/http"
@@ -68,9 +67,9 @@ func BodyDumpWithConfig(config BodyDumpConfig) echo.MiddlewareFunc {
// Request
reqBody := []byte{}
if c.Request().Body != nil { // Read
- reqBody, _ = ioutil.ReadAll(c.Request().Body)
+ reqBody, _ = io.ReadAll(c.Request().Body)
}
- c.Request().Body = ioutil.NopCloser(bytes.NewBuffer(reqBody)) // Reset
+ c.Request().Body = io.NopCloser(bytes.NewBuffer(reqBody)) // Reset
// Response
resBody := new(bytes.Buffer)
diff --git a/vendor/github.com/labstack/echo/v4/middleware/compress.go b/vendor/github.com/labstack/echo/v4/middleware/compress.go
index ac6672e9..9e5f6106 100644
--- a/vendor/github.com/labstack/echo/v4/middleware/compress.go
+++ b/vendor/github.com/labstack/echo/v4/middleware/compress.go
@@ -4,7 +4,6 @@ import (
"bufio"
"compress/gzip"
"io"
- "io/ioutil"
"net"
"net/http"
"strings"
@@ -89,7 +88,7 @@ func GzipWithConfig(config GzipConfig) echo.MiddlewareFunc {
// nothing is written to body or error is returned.
// See issue #424, #407.
res.Writer = rw
- w.Reset(ioutil.Discard)
+ w.Reset(io.Discard)
}
w.Close()
pool.Put(w)
@@ -135,7 +134,7 @@ func (w *gzipResponseWriter) Push(target string, opts *http.PushOptions) error {
func gzipCompressPool(config GzipConfig) sync.Pool {
return sync.Pool{
New: func() interface{} {
- w, err := gzip.NewWriterLevel(ioutil.Discard, config.Level)
+ w, err := gzip.NewWriterLevel(io.Discard, config.Level)
if err != nil {
return err
}
diff --git a/vendor/github.com/labstack/echo/v4/middleware/csrf.go b/vendor/github.com/labstack/echo/v4/middleware/csrf.go
index ea90fdba..8661c9f8 100644
--- a/vendor/github.com/labstack/echo/v4/middleware/csrf.go
+++ b/vendor/github.com/labstack/echo/v4/middleware/csrf.go
@@ -119,7 +119,7 @@ func CSRFWithConfig(config CSRFConfig) echo.MiddlewareFunc {
config.CookieSecure = true
}
- extractors, err := createExtractors(config.TokenLookup, "")
+ extractors, err := CreateExtractors(config.TokenLookup)
if err != nil {
panic(err)
}
diff --git a/vendor/github.com/labstack/echo/v4/middleware/extractor.go b/vendor/github.com/labstack/echo/v4/middleware/extractor.go
index afdfd819..5d9cee6d 100644
--- a/vendor/github.com/labstack/echo/v4/middleware/extractor.go
+++ b/vendor/github.com/labstack/echo/v4/middleware/extractor.go
@@ -24,6 +24,26 @@ var errFormExtractorValueMissing = errors.New("missing value in the form")
// ValuesExtractor defines a function for extracting values (keys/tokens) from the given context.
type ValuesExtractor func(c echo.Context) ([]string, error)
+// CreateExtractors creates ValuesExtractors from given lookups.
+// Lookups is a string in the form of "<source>:<name>" or "<source>:<name>,<source>:<name>" that is used
+// to extract key from the request.
+// Possible values:
+// - "header:<name>" or "header:<name>:<cut-prefix>"
+// `<cut-prefix>` is argument value to cut/trim prefix of the extracted value. This is useful if header
+// value has static prefix like `Authorization: <auth-scheme> <authorisation-parameters>` where part that we
+// want to cut is `<auth-scheme> ` note the space at the end.
+// In case of basic authentication `Authorization: Basic <credentials>` prefix we want to remove is `Basic `.
+// - "query:<name>"
+// - "param:<name>"
+// - "form:<name>"
+// - "cookie:<name>"
+//
+// Multiple sources example:
+// - "header:Authorization,header:X-Api-Key"
+func CreateExtractors(lookups string) ([]ValuesExtractor, error) {
+ return createExtractors(lookups, "")
+}
+
func createExtractors(lookups string, authScheme string) ([]ValuesExtractor, error) {
if lookups == "" {
return nil, nil
diff --git a/vendor/github.com/labstack/echo/v4/middleware/jwt.go b/vendor/github.com/labstack/echo/v4/middleware/jwt.go
index bec5167e..bd628264 100644
--- a/vendor/github.com/labstack/echo/v4/middleware/jwt.go
+++ b/vendor/github.com/labstack/echo/v4/middleware/jwt.go
@@ -154,6 +154,8 @@ var (
//
// See: https://jwt.io/introduction
// See `JWTConfig.TokenLookup`
+//
+// Deprecated: Please use https://github.com/labstack/echo-jwt instead
func JWT(key interface{}) echo.MiddlewareFunc {
c := DefaultJWTConfig
c.SigningKey = key
@@ -162,6 +164,8 @@ func JWT(key interface{}) echo.MiddlewareFunc {
// JWTWithConfig returns a JWT auth middleware with config.
// See: `JWT()`.
+//
+// Deprecated: Please use https://github.com/labstack/echo-jwt instead
func JWTWithConfig(config JWTConfig) echo.MiddlewareFunc {
// Defaults
if config.Skipper == nil {
@@ -262,7 +266,7 @@ func JWTWithConfig(config JWTConfig) echo.MiddlewareFunc {
}
func (config *JWTConfig) defaultParseToken(auth string, c echo.Context) (interface{}, error) {
- token := new(jwt.Token)
+ var token *jwt.Token
var err error
// Issue #647, #656
if _, ok := config.Claims.(jwt.MapClaims); ok {
diff --git a/vendor/github.com/labstack/echo/v4/middleware/logger.go b/vendor/github.com/labstack/echo/v4/middleware/logger.go
index a21df8f3..7958d873 100644
--- a/vendor/github.com/labstack/echo/v4/middleware/logger.go
+++ b/vendor/github.com/labstack/echo/v4/middleware/logger.go
@@ -35,6 +35,7 @@ type (
// - host
// - method
// - path
+ // - route
// - protocol
// - referer
// - user_agent
@@ -47,6 +48,7 @@ type (
// - header:<NAME>
// - query:<NAME>
// - form:<NAME>
+ // - custom (see CustomTagFunc field)
//
// Example "${remote_ip} ${status}"
//
@@ -56,6 +58,11 @@ type (
// Optional. Default value DefaultLoggerConfig.CustomTimeFormat.
CustomTimeFormat string `yaml:"custom_time_format"`
+ // CustomTagFunc is function called for `${custom}` tag to output user implemented text by writing it to buf.
+ // Make sure that outputted text creates valid JSON string with other logged tags.
+ // Optional.
+ CustomTagFunc func(c echo.Context, buf *bytes.Buffer) (int, error)
+
// Output is a writer where logs in JSON format are written.
// Optional. Default value os.Stdout.
Output io.Writer
@@ -126,6 +133,11 @@ func LoggerWithConfig(config LoggerConfig) echo.MiddlewareFunc {
if _, err = config.template.ExecuteFunc(buf, func(w io.Writer, tag string) (int, error) {
switch tag {
+ case "custom":
+ if config.CustomTagFunc == nil {
+ return 0, nil
+ }
+ return config.CustomTagFunc(c, buf)
case "time_unix":
return buf.WriteString(strconv.FormatInt(time.Now().Unix(), 10))
case "time_unix_milli":
@@ -162,6 +174,8 @@ func LoggerWithConfig(config LoggerConfig) echo.MiddlewareFunc {
p = "/"
}
return buf.WriteString(p)
+ case "route":
+ return buf.WriteString(c.Path())
case "protocol":
return buf.WriteString(req.Proto)
case "referer":
diff --git a/vendor/github.com/labstack/echo/v4/middleware/proxy.go b/vendor/github.com/labstack/echo/v4/middleware/proxy.go
index 6cfd6731..d2cd2aa6 100644
--- a/vendor/github.com/labstack/echo/v4/middleware/proxy.go
+++ b/vendor/github.com/labstack/echo/v4/middleware/proxy.go
@@ -72,6 +72,11 @@ type (
Next(echo.Context) *ProxyTarget
}
+ // TargetProvider defines an interface that gives the opportunity for balancer to return custom errors when selecting target.
+ TargetProvider interface {
+ NextTarget(echo.Context) (*ProxyTarget, error)
+ }
+
commonBalancer struct {
targets []*ProxyTarget
mutex sync.RWMutex
@@ -223,6 +228,7 @@ func ProxyWithConfig(config ProxyConfig) echo.MiddlewareFunc {
}
}
+ provider, isTargetProvider := config.Balancer.(TargetProvider)
return func(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) (err error) {
if config.Skipper(c) {
@@ -231,7 +237,16 @@ func ProxyWithConfig(config ProxyConfig) echo.MiddlewareFunc {
req := c.Request()
res := c.Response()
- tgt := config.Balancer.Next(c)
+
+ var tgt *ProxyTarget
+ if isTargetProvider {
+ tgt, err = provider.NextTarget(c)
+ if err != nil {
+ return err
+ }
+ } else {
+ tgt = config.Balancer.Next(c)
+ }
c.Set(config.ContextKey, tgt)
if err := rewriteURL(config.RegexRewrite, req); err != nil {
diff --git a/vendor/github.com/labstack/echo/v4/middleware/rate_limiter.go b/vendor/github.com/labstack/echo/v4/middleware/rate_limiter.go
index be2b348d..f7fae83c 100644
--- a/vendor/github.com/labstack/echo/v4/middleware/rate_limiter.go
+++ b/vendor/github.com/labstack/echo/v4/middleware/rate_limiter.go
@@ -155,7 +155,7 @@ type (
RateLimiterMemoryStore struct {
visitors map[string]*Visitor
mutex sync.Mutex
- rate rate.Limit //for more info check out Limiter docs - https://pkg.go.dev/golang.org/x/time/rate#Limit.
+ rate rate.Limit // for more info check out Limiter docs - https://pkg.go.dev/golang.org/x/time/rate#Limit.
burst int
expiresIn time.Duration
@@ -170,15 +170,16 @@ type (
/*
NewRateLimiterMemoryStore returns an instance of RateLimiterMemoryStore with
-the provided rate (as req/s). The provided rate less than 1 will be treated as zero.
+the provided rate (as req/s).
for more info check out Limiter docs - https://pkg.go.dev/golang.org/x/time/rate#Limit.
Burst and ExpiresIn will be set to default values.
+Note that if the provided rate is a float number and Burst is zero, Burst will be treated as the rounded down value of the rate.
+
Example (with 20 requests/sec):
limiterStore := middleware.NewRateLimiterMemoryStore(20)
-
*/
func NewRateLimiterMemoryStore(rate rate.Limit) (store *RateLimiterMemoryStore) {
return NewRateLimiterMemoryStoreWithConfig(RateLimiterMemoryStoreConfig{
@@ -188,7 +189,7 @@ func NewRateLimiterMemoryStore(rate rate.Limit) (store *RateLimiterMemoryStore)
/*
NewRateLimiterMemoryStoreWithConfig returns an instance of RateLimiterMemoryStore
-with the provided configuration. Rate must be provided. Burst will be set to the value of
+with the provided configuration. Rate must be provided. Burst will be set to the rounded down value of
the configured rate if not provided or set to 0.
The build-in memory store is usually capable for modest loads. For higher loads other
@@ -225,7 +226,7 @@ func NewRateLimiterMemoryStoreWithConfig(config RateLimiterMemoryStoreConfig) (s
// RateLimiterMemoryStoreConfig represents configuration for RateLimiterMemoryStore
type RateLimiterMemoryStoreConfig struct {
Rate rate.Limit // Rate of requests allowed to pass as req/s. For more info check out Limiter docs - https://pkg.go.dev/golang.org/x/time/rate#Limit.
- Burst int // Burst additionally allows a number of requests to pass when rate limit is reached
+ Burst int // Burst is maximum number of requests to pass at the same moment. It additionally allows a number of requests to pass when rate limit is reached.
ExpiresIn time.Duration // ExpiresIn is the duration after that a rate limiter is cleaned up
}
diff --git a/vendor/github.com/labstack/echo/v4/middleware/request_logger.go b/vendor/github.com/labstack/echo/v4/middleware/request_logger.go
index 7a4d9822..b9e36925 100644
--- a/vendor/github.com/labstack/echo/v4/middleware/request_logger.go
+++ b/vendor/github.com/labstack/echo/v4/middleware/request_logger.go
@@ -10,10 +10,16 @@ import (
// Example for `fmt.Printf`
// e.Use(middleware.RequestLoggerWithConfig(middleware.RequestLoggerConfig{
-// LogStatus: true,
-// LogURI: true,
+// LogStatus: true,
+// LogURI: true,
+// LogError: true,
+// HandleError: true, // forwards error to the global error handler, so it can decide appropriate status code
// LogValuesFunc: func(c echo.Context, v middleware.RequestLoggerValues) error {
-// fmt.Printf("REQUEST: uri: %v, status: %v\n", v.URI, v.Status)
+// if v.Error == nil {
+// fmt.Printf("REQUEST: uri: %v, status: %v\n", v.URI, v.Status)
+// } else {
+// fmt.Printf("REQUEST_ERROR: uri: %v, status: %v, err: %v\n", v.URI, v.Status, v.Error)
+// }
// return nil
// },
// }))
@@ -21,14 +27,23 @@ import (
// Example for Zerolog (https://github.com/rs/zerolog)
// logger := zerolog.New(os.Stdout)
// e.Use(middleware.RequestLoggerWithConfig(middleware.RequestLoggerConfig{
-// LogURI: true,
-// LogStatus: true,
+// LogURI: true,
+// LogStatus: true,
+// LogError: true,
+// HandleError: true, // forwards error to the global error handler, so it can decide appropriate status code
// LogValuesFunc: func(c echo.Context, v middleware.RequestLoggerValues) error {
-// logger.Info().
-// Str("URI", v.URI).
-// Int("status", v.Status).
-// Msg("request")
-//
+// if v.Error == nil {
+// logger.Info().
+// Str("URI", v.URI).
+// Int("status", v.Status).
+// Msg("request")
+// } else {
+// logger.Error().
+// Err(v.Error).
+// Str("URI", v.URI).
+// Int("status", v.Status).
+// Msg("request error")
+// }
// return nil
// },
// }))
@@ -36,29 +51,47 @@ import (
// Example for Zap (https://github.com/uber-go/zap)
// logger, _ := zap.NewProduction()
// e.Use(middleware.RequestLoggerWithConfig(middleware.RequestLoggerConfig{
-// LogURI: true,
-// LogStatus: true,
+// LogURI: true,
+// LogStatus: true,
+// LogError: true,
+// HandleError: true, // forwards error to the global error handler, so it can decide appropriate status code
// LogValuesFunc: func(c echo.Context, v middleware.RequestLoggerValues) error {
-// logger.Info("request",
-// zap.String("URI", v.URI),
-// zap.Int("status", v.Status),
-// )
-//
+// if v.Error == nil {
+// logger.Info("request",
+// zap.String("URI", v.URI),
+// zap.Int("status", v.Status),
+// )
+// } else {
+// logger.Error("request error",
+// zap.String("URI", v.URI),
+// zap.Int("status", v.Status),
+// zap.Error(v.Error),
+// )
+// }
// return nil
// },
// }))
//
// Example for Logrus (https://github.com/sirupsen/logrus)
-// log := logrus.New()
+// log := logrus.New()
// e.Use(middleware.RequestLoggerWithConfig(middleware.RequestLoggerConfig{
-// LogURI: true,
-// LogStatus: true,
-// LogValuesFunc: func(c echo.Context, values middleware.RequestLoggerValues) error {
-// log.WithFields(logrus.Fields{
-// "URI": values.URI,
-// "status": values.Status,
-// }).Info("request")
-//
+// LogURI: true,
+// LogStatus: true,
+// LogError: true,
+// HandleError: true, // forwards error to the global error handler, so it can decide appropriate status code
+// LogValuesFunc: func(c echo.Context, v middleware.RequestLoggerValues) error {
+// if v.Error == nil {
+// log.WithFields(logrus.Fields{
+// "URI": v.URI,
+// "status": v.Status,
+// }).Info("request")
+// } else {
+// log.WithFields(logrus.Fields{
+// "URI": v.URI,
+// "status": v.Status,
+// "error": v.Error,
+// }).Error("request error")
+// }
// return nil
// },
// }))
@@ -74,6 +107,13 @@ type RequestLoggerConfig struct {
// Mandatory.
LogValuesFunc func(c echo.Context, v RequestLoggerValues) error
+ // HandleError instructs logger to call global error handler when next middleware/handler returns an error.
+ // This is useful when you have custom error handler that can decide to use different status codes.
+ //
+ // A side-effect of calling global error handler is that now Response has been committed and sent to the client
+ // and middlewares up in chain can not change Response status code or response body.
+ HandleError bool
+
// LogLatency instructs logger to record duration it took to execute rest of the handler chain (next(c) call).
LogLatency bool
// LogProtocol instructs logger to extract request protocol (i.e. `HTTP/1.1` or `HTTP/2`)
@@ -217,6 +257,9 @@ func (config RequestLoggerConfig) ToMiddleware() (echo.MiddlewareFunc, error) {
config.BeforeNextFunc(c)
}
err := next(c)
+ if config.HandleError {
+ c.Error(err)
+ }
v := RequestLoggerValues{
StartTime: start,
@@ -264,7 +307,9 @@ func (config RequestLoggerConfig) ToMiddleware() (echo.MiddlewareFunc, error) {
}
if config.LogStatus {
v.Status = res.Status
- if err != nil {
+ if err != nil && !config.HandleError {
+ // this block should not be executed in case of HandleError=true as the global error handler will decide
+ // the status code. In that case status code could be different from what err contains.
var httpErr *echo.HTTPError
if errors.As(err, &httpErr) {
v.Status = httpErr.Code
@@ -310,6 +355,9 @@ func (config RequestLoggerConfig) ToMiddleware() (echo.MiddlewareFunc, error) {
return errOnLog
}
+ // in case of HandleError=true we are returning the error that we already have handled with global error handler
+ // this is deliberate as this error could be useful for upstream middlewares and default global error handler
+ // will ignore that error when it bubbles up in middleware chain.
return err
}
}, nil
diff --git a/vendor/github.com/labstack/echo/v4/middleware/slash.go b/vendor/github.com/labstack/echo/v4/middleware/slash.go
index 4188675b..a3bf807e 100644
--- a/vendor/github.com/labstack/echo/v4/middleware/slash.go
+++ b/vendor/github.com/labstack/echo/v4/middleware/slash.go
@@ -33,7 +33,7 @@ func AddTrailingSlash() echo.MiddlewareFunc {
return AddTrailingSlashWithConfig(DefaultTrailingSlashConfig)
}
-// AddTrailingSlashWithConfig returns a AddTrailingSlash middleware with config.
+// AddTrailingSlashWithConfig returns an AddTrailingSlash middleware with config.
// See `AddTrailingSlash()`.
func AddTrailingSlashWithConfig(config TrailingSlashConfig) echo.MiddlewareFunc {
// Defaults
diff --git a/vendor/github.com/labstack/echo/v4/router.go b/vendor/github.com/labstack/echo/v4/router.go
index 23c5bd3b..86a986a2 100644
--- a/vendor/github.com/labstack/echo/v4/router.go
+++ b/vendor/github.com/labstack/echo/v4/router.go
@@ -2,6 +2,7 @@ package echo
import (
"bytes"
+ "fmt"
"net/http"
)
@@ -141,6 +142,51 @@ func NewRouter(e *Echo) *Router {
}
}
+// Routes returns the registered routes.
+func (r *Router) Routes() []*Route {
+ routes := make([]*Route, 0, len(r.routes))
+ for _, v := range r.routes {
+ routes = append(routes, v)
+ }
+ return routes
+}
+
+// Reverse generates an URL from route name and provided parameters.
+func (r *Router) Reverse(name string, params ...interface{}) string {
+ uri := new(bytes.Buffer)
+ ln := len(params)
+ n := 0
+ for _, route := range r.routes {
+ if route.Name == name {
+ for i, l := 0, len(route.Path); i < l; i++ {
+ if (route.Path[i] == ':' || route.Path[i] == '*') && n < ln {
+ for ; i < l && route.Path[i] != '/'; i++ {
+ }
+ uri.WriteString(fmt.Sprintf("%v", params[n]))
+ n++
+ }
+ if i < l {
+ uri.WriteByte(route.Path[i])
+ }
+ }
+ break
+ }
+ }
+ return uri.String()
+}
+
+func (r *Router) add(method, path, name string, h HandlerFunc) *Route {
+ r.Add(method, path, h)
+
+ route := &Route{
+ Method: method,
+ Path: path,
+ Name: name,
+ }
+ r.routes[method+path] = route
+ return route
+}
+
// Add registers a new route for method and path with matching handler.
func (r *Router) Add(method, path string, h HandlerFunc) {
// Validate path
diff --git a/vendor/github.com/lrstanley/girc/.editorconfig b/vendor/github.com/lrstanley/girc/.editorconfig
index 6df59d5c..32ecf3ee 100644
--- a/vendor/github.com/lrstanley/girc/.editorconfig
+++ b/vendor/github.com/lrstanley/girc/.editorconfig
@@ -22,7 +22,7 @@ indent_size = 4
[*.md]
trim_trailing_whitespace = false
-[*.{md,py,sh,yml,yaml,js,ts,vue,css}]
+[*.{md,py,sh,yml,yaml,cjs,js,ts,vue,css}]
max_line_length = 105
[*.{yml,yaml,toml}]
@@ -36,7 +36,7 @@ insert_final_newline = ignore
max_line_length = 140
indent_size = 2
-[*.{js,ts,vue,css}]
+[*.{cjs,js,ts,vue,css}]
indent_size = 2
[Makefile]
diff --git a/vendor/github.com/lrstanley/girc/README.md b/vendor/github.com/lrstanley/girc/README.md
index 19670eae..ddb0bc1b 100644
--- a/vendor/github.com/lrstanley/girc/README.md
+++ b/vendor/github.com/lrstanley/girc/README.md
@@ -12,7 +12,7 @@
</a>
<a href="https://github.com/lrstanley/girc/actions?query=workflow%3Atest+event%3Apush">
- <img title="GitHub Workflow Status (test @ master)" src="https://img.shields.io/github/workflow/status/lrstanley/girc/test/master?label=test&style=flat-square&event=push">
+ <img title="GitHub Workflow Status (test @ master)" src="https://img.shields.io/github/actions/workflow/status/lrstanley/girc/test.yml?branch=master&label=test&style=flat-square">
</a>
<a href="https://codecov.io/gh/lrstanley/girc">
diff --git a/vendor/github.com/magiconair/properties/.travis.yml b/vendor/github.com/magiconair/properties/.travis.yml
deleted file mode 100644
index baf9031d..00000000
--- a/vendor/github.com/magiconair/properties/.travis.yml
+++ /dev/null
@@ -1,17 +0,0 @@
-language: go
-go:
- - 1.3.x
- - 1.4.x
- - 1.5.x
- - 1.6.x
- - 1.7.x
- - 1.8.x
- - 1.9.x
- - "1.10.x"
- - "1.11.x"
- - "1.12.x"
- - "1.13.x"
- - "1.14.x"
- - "1.15.x"
- - "1.16.x"
- - tip
diff --git a/vendor/github.com/magiconair/properties/CHANGELOG.md b/vendor/github.com/magiconair/properties/CHANGELOG.md
index ff8d0253..842e8e24 100644
--- a/vendor/github.com/magiconair/properties/CHANGELOG.md
+++ b/vendor/github.com/magiconair/properties/CHANGELOG.md
@@ -1,5 +1,50 @@
## Changelog
+### [1.8.7](https://github.com/magiconair/properties/tree/v1.8.7) - 08 Dec 2022
+
+ * [PR #65](https://github.com/magiconair/properties/pull/65): Speedup Merge
+
+ Thanks to [@AdityaVallabh](https://github.com/AdityaVallabh) for the patch.
+
+ * [PR #66](https://github.com/magiconair/properties/pull/66): use github actions
+
+### [1.8.6](https://github.com/magiconair/properties/tree/v1.8.6) - 23 Feb 2022
+
+ * [PR #57](https://github.com/magiconair/properties/pull/57):Fix "unreachable code" lint error
+
+ Thanks to [@ellie](https://github.com/ellie) for the patch.
+
+ * [PR #63](https://github.com/magiconair/properties/pull/63): Make TestMustGetParsedDuration backwards compatible
+
+ This patch ensures that the `TestMustGetParsedDuration` still works with `go1.3` to make the
+ author happy until it affects real users.
+
+ Thanks to [@maage](https://github.com/maage) for the patch.
+
+### [1.8.5](https://github.com/magiconair/properties/tree/v1.8.5) - 24 Mar 2021
+
+ * [PR #55](https://github.com/magiconair/properties/pull/55): Fix: Encoding Bug in Comments
+
+ When reading comments \ are loaded correctly, but when writing they are then
+ replaced by \\. This leads to wrong comments when writing and reading multiple times.
+
+ Thanks to [@doxsch](https://github.com/doxsch) for the patch.
+
+### [1.8.4](https://github.com/magiconair/properties/tree/v1.8.4) - 23 Sep 2020
+
+ * [PR #50](https://github.com/magiconair/properties/pull/50): enhance error message for circular references
+
+ Thanks to [@sriv](https://github.com/sriv) for the patch.
+
+### [1.8.3](https://github.com/magiconair/properties/tree/v1.8.3) - 14 Sep 2020
+
+ * [PR #49](https://github.com/magiconair/properties/pull/49): Include the key in error message causing the circular reference
+
+ The change is include the key in the error message which is causing the circular
+ reference when parsing/loading the properties files.
+
+ Thanks to [@haroon-sheikh](https://github.com/haroon-sheikh) for the patch.
+
### [1.8.2](https://github.com/magiconair/properties/tree/v1.8.2) - 25 Aug 2020
* [PR #36](https://github.com/magiconair/properties/pull/36): Escape backslash on write
diff --git a/vendor/github.com/magiconair/properties/decode.go b/vendor/github.com/magiconair/properties/decode.go
index 3ebf8049..8e6aa441 100644
--- a/vendor/github.com/magiconair/properties/decode.go
+++ b/vendor/github.com/magiconair/properties/decode.go
@@ -1,4 +1,4 @@
-// Copyright 2018 Frank Schroeder. All rights reserved.
+// Copyright 2013-2022 Frank Schroeder. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -48,49 +48,49 @@ import (
//
// Examples:
//
-// // Field is ignored.
-// Field int `properties:"-"`
+// // Field is ignored.
+// Field int `properties:"-"`
//
-// // Field is assigned value of 'Field'.
-// Field int
+// // Field is assigned value of 'Field'.
+// Field int
//
-// // Field is assigned value of 'myName'.
-// Field int `properties:"myName"`
+// // Field is assigned value of 'myName'.
+// Field int `properties:"myName"`
//
-// // Field is assigned value of key 'myName' and has a default
-// // value 15 if the key does not exist.
-// Field int `properties:"myName,default=15"`
+// // Field is assigned value of key 'myName' and has a default
+// // value 15 if the key does not exist.
+// Field int `properties:"myName,default=15"`
//
-// // Field is assigned value of key 'Field' and has a default
-// // value 15 if the key does not exist.
-// Field int `properties:",default=15"`
+// // Field is assigned value of key 'Field' and has a default
+// // value 15 if the key does not exist.
+// Field int `properties:",default=15"`
//
-// // Field is assigned value of key 'date' and the date
-// // is in format 2006-01-02
-// Field time.Time `properties:"date,layout=2006-01-02"`
+// // Field is assigned value of key 'date' and the date
+// // is in format 2006-01-02
+// Field time.Time `properties:"date,layout=2006-01-02"`
//
-// // Field is assigned the non-empty and whitespace trimmed
-// // values of key 'Field' split by commas.
-// Field []string
+// // Field is assigned the non-empty and whitespace trimmed
+// // values of key 'Field' split by commas.
+// Field []string
//
-// // Field is assigned the non-empty and whitespace trimmed
-// // values of key 'Field' split by commas and has a default
-// // value ["a", "b", "c"] if the key does not exist.
-// Field []string `properties:",default=a;b;c"`
+// // Field is assigned the non-empty and whitespace trimmed
+// // values of key 'Field' split by commas and has a default
+// // value ["a", "b", "c"] if the key does not exist.
+// Field []string `properties:",default=a;b;c"`
//
-// // Field is decoded recursively with "Field." as key prefix.
-// Field SomeStruct
+// // Field is decoded recursively with "Field." as key prefix.
+// Field SomeStruct
//
-// // Field is decoded recursively with "myName." as key prefix.
-// Field SomeStruct `properties:"myName"`
+// // Field is decoded recursively with "myName." as key prefix.
+// Field SomeStruct `properties:"myName"`
//
-// // Field is decoded recursively with "Field." as key prefix
-// // and the next dotted element of the key as map key.
-// Field map[string]string
+// // Field is decoded recursively with "Field." as key prefix
+// // and the next dotted element of the key as map key.
+// Field map[string]string
//
-// // Field is decoded recursively with "myName." as key prefix
-// // and the next dotted element of the key as map key.
-// Field map[string]string `properties:"myName"`
+// // Field is decoded recursively with "myName." as key prefix
+// // and the next dotted element of the key as map key.
+// Field map[string]string `properties:"myName"`
func (p *Properties) Decode(x interface{}) error {
t, v := reflect.TypeOf(x), reflect.ValueOf(x)
if t.Kind() != reflect.Ptr || v.Elem().Type().Kind() != reflect.Struct {
diff --git a/vendor/github.com/magiconair/properties/doc.go b/vendor/github.com/magiconair/properties/doc.go
index f8822da2..7c797931 100644
--- a/vendor/github.com/magiconair/properties/doc.go
+++ b/vendor/github.com/magiconair/properties/doc.go
@@ -1,4 +1,4 @@
-// Copyright 2018 Frank Schroeder. All rights reserved.
+// Copyright 2013-2022 Frank Schroeder. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -13,7 +13,7 @@
//
// To load a single properties file use MustLoadFile():
//
-// p := properties.MustLoadFile(filename, properties.UTF8)
+// p := properties.MustLoadFile(filename, properties.UTF8)
//
// To load multiple properties files use MustLoadFiles()
// which loads the files in the given order and merges the
@@ -23,25 +23,25 @@
// Filenames can contain environment variables which are expanded
// before loading.
//
-// f1 := "/etc/myapp/myapp.conf"
-// f2 := "/home/${USER}/myapp.conf"
-// p := MustLoadFiles([]string{f1, f2}, properties.UTF8, true)
+// f1 := "/etc/myapp/myapp.conf"
+// f2 := "/home/${USER}/myapp.conf"
+// p := MustLoadFiles([]string{f1, f2}, properties.UTF8, true)
//
// All of the different key/value delimiters ' ', ':' and '=' are
// supported as well as the comment characters '!' and '#' and
// multi-line values.
//
-// ! this is a comment
-// # and so is this
+// ! this is a comment
+// # and so is this
//
-// # the following expressions are equal
-// key value
-// key=value
-// key:value
-// key = value
-// key : value
-// key = val\
-// ue
+// # the following expressions are equal
+// key value
+// key=value
+// key:value
+// key = value
+// key : value
+// key = val\
+// ue
//
// Properties stores all comments preceding a key and provides
// GetComments() and SetComments() methods to retrieve and
@@ -55,62 +55,62 @@
// and malformed expressions are not allowed and cause an
// error. Expansion of environment variables is supported.
//
-// # standard property
-// key = value
+// # standard property
+// key = value
//
-// # property expansion: key2 = value
-// key2 = ${key}
+// # property expansion: key2 = value
+// key2 = ${key}
//
-// # recursive expansion: key3 = value
-// key3 = ${key2}
+// # recursive expansion: key3 = value
+// key3 = ${key2}
//
-// # circular reference (error)
-// key = ${key}
+// # circular reference (error)
+// key = ${key}
//
-// # malformed expression (error)
-// key = ${ke
+// # malformed expression (error)
+// key = ${ke
//
-// # refers to the users' home dir
-// home = ${HOME}
+// # refers to the users' home dir
+// home = ${HOME}
//
-// # local key takes precedence over env var: u = foo
-// USER = foo
-// u = ${USER}
+// # local key takes precedence over env var: u = foo
+// USER = foo
+// u = ${USER}
//
// The default property expansion format is ${key} but can be
// changed by setting different pre- and postfix values on the
// Properties object.
//
-// p := properties.NewProperties()
-// p.Prefix = "#["
-// p.Postfix = "]#"
+// p := properties.NewProperties()
+// p.Prefix = "#["
+// p.Postfix = "]#"
//
// Properties provides convenience functions for getting typed
// values with default values if the key does not exist or the
// type conversion failed.
//
-// # Returns true if the value is either "1", "on", "yes" or "true"
-// # Returns false for every other value and the default value if
-// # the key does not exist.
-// v = p.GetBool("key", false)
+// # Returns true if the value is either "1", "on", "yes" or "true"
+// # Returns false for every other value and the default value if
+// # the key does not exist.
+// v = p.GetBool("key", false)
//
-// # Returns the value if the key exists and the format conversion
-// # was successful. Otherwise, the default value is returned.
-// v = p.GetInt64("key", 999)
-// v = p.GetUint64("key", 999)
-// v = p.GetFloat64("key", 123.0)
-// v = p.GetString("key", "def")
-// v = p.GetDuration("key", 999)
+// # Returns the value if the key exists and the format conversion
+// # was successful. Otherwise, the default value is returned.
+// v = p.GetInt64("key", 999)
+// v = p.GetUint64("key", 999)
+// v = p.GetFloat64("key", 123.0)
+// v = p.GetString("key", "def")
+// v = p.GetDuration("key", 999)
//
// As an alternative properties may be applied with the standard
// library's flag implementation at any time.
//
-// # Standard configuration
-// v = flag.Int("key", 999, "help message")
-// flag.Parse()
+// # Standard configuration
+// v = flag.Int("key", 999, "help message")
+// flag.Parse()
//
-// # Merge p into the flag set
-// p.MustFlag(flag.CommandLine)
+// # Merge p into the flag set
+// p.MustFlag(flag.CommandLine)
//
// Properties provides several MustXXX() convenience functions
// which will terminate the app if an error occurs. The behavior
@@ -119,30 +119,30 @@
// of logging the error set a different ErrorHandler before
// you use the Properties package.
//
-// properties.ErrorHandler = properties.PanicHandler
+// properties.ErrorHandler = properties.PanicHandler
//
-// # Will panic instead of logging an error
-// p := properties.MustLoadFile("config.properties")
+// # Will panic instead of logging an error
+// p := properties.MustLoadFile("config.properties")
//
// You can also provide your own ErrorHandler function. The only requirement
// is that the error handler function must exit after handling the error.
//
-// properties.ErrorHandler = func(err error) {
-// fmt.Println(err)
-// os.Exit(1)
-// }
+// properties.ErrorHandler = func(err error) {
+// fmt.Println(err)
+// os.Exit(1)
+// }
//
-// # Will write to stdout and then exit
-// p := properties.MustLoadFile("config.properties")
+// # Will write to stdout and then exit
+// p := properties.MustLoadFile("config.properties")
//
// Properties can also be loaded into a struct via the `Decode`
// method, e.g.
//
-// type S struct {
-// A string `properties:"a,default=foo"`
-// D time.Duration `properties:"timeout,default=5s"`
-// E time.Time `properties:"expires,layout=2006-01-02,default=2015-01-01"`
-// }
+// type S struct {
+// A string `properties:"a,default=foo"`
+// D time.Duration `properties:"timeout,default=5s"`
+// E time.Time `properties:"expires,layout=2006-01-02,default=2015-01-01"`
+// }
//
// See `Decode()` method for the full documentation.
//
@@ -152,5 +152,4 @@
// http://en.wikipedia.org/wiki/.properties
//
// http://docs.oracle.com/javase/7/docs/api/java/util/Properties.html#load%28java.io.Reader%29
-//
package properties
diff --git a/vendor/github.com/magiconair/properties/integrate.go b/vendor/github.com/magiconair/properties/integrate.go
index 74d38dc6..35d0ae97 100644
--- a/vendor/github.com/magiconair/properties/integrate.go
+++ b/vendor/github.com/magiconair/properties/integrate.go
@@ -1,4 +1,4 @@
-// Copyright 2018 Frank Schroeder. All rights reserved.
+// Copyright 2013-2022 Frank Schroeder. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -10,8 +10,9 @@ import "flag"
// the respective key for flag.Flag.Name.
//
// It's use is recommended with command line arguments as in:
-// flag.Parse()
-// p.MustFlag(flag.CommandLine)
+//
+// flag.Parse()
+// p.MustFlag(flag.CommandLine)
func (p *Properties) MustFlag(dst *flag.FlagSet) {
m := make(map[string]*flag.Flag)
dst.VisitAll(func(f *flag.Flag) {
diff --git a/vendor/github.com/magiconair/properties/lex.go b/vendor/github.com/magiconair/properties/lex.go
index e1e9dd7b..3d15a1f6 100644
--- a/vendor/github.com/magiconair/properties/lex.go
+++ b/vendor/github.com/magiconair/properties/lex.go
@@ -1,4 +1,4 @@
-// Copyright 2018 Frank Schroeder. All rights reserved.
+// Copyright 2013-2022 Frank Schroeder. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//
diff --git a/vendor/github.com/magiconair/properties/load.go b/vendor/github.com/magiconair/properties/load.go
index c83c2dad..635368dc 100644
--- a/vendor/github.com/magiconair/properties/load.go
+++ b/vendor/github.com/magiconair/properties/load.go
@@ -1,4 +1,4 @@
-// Copyright 2018 Frank Schroeder. All rights reserved.
+// Copyright 2013-2022 Frank Schroeder. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/vendor/github.com/magiconair/properties/parser.go b/vendor/github.com/magiconair/properties/parser.go
index 430e4fcd..fccfd39f 100644
--- a/vendor/github.com/magiconair/properties/parser.go
+++ b/vendor/github.com/magiconair/properties/parser.go
@@ -1,4 +1,4 @@
-// Copyright 2018 Frank Schroeder. All rights reserved.
+// Copyright 2013-2022 Frank Schroeder. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/vendor/github.com/magiconair/properties/properties.go b/vendor/github.com/magiconair/properties/properties.go
index 62ae2d67..fb2f7b40 100644
--- a/vendor/github.com/magiconair/properties/properties.go
+++ b/vendor/github.com/magiconair/properties/properties.go
@@ -1,4 +1,4 @@
-// Copyright 2018 Frank Schroeder. All rights reserved.
+// Copyright 2013-2022 Frank Schroeder. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -700,22 +700,17 @@ func (p *Properties) Delete(key string) {
// Merge merges properties, comments and keys from other *Properties into p
func (p *Properties) Merge(other *Properties) {
+ for _, k := range other.k {
+ if _, ok := p.m[k]; !ok {
+ p.k = append(p.k, k)
+ }
+ }
for k, v := range other.m {
p.m[k] = v
}
for k, v := range other.c {
p.c[k] = v
}
-
-outer:
- for _, otherKey := range other.k {
- for _, key := range p.k {
- if otherKey == key {
- continue outer
- }
- }
- p.k = append(p.k, otherKey)
- }
}
// ----------------------------------------------------------------------------
diff --git a/vendor/github.com/magiconair/properties/rangecheck.go b/vendor/github.com/magiconair/properties/rangecheck.go
index b013a2e5..dbd60b36 100644
--- a/vendor/github.com/magiconair/properties/rangecheck.go
+++ b/vendor/github.com/magiconair/properties/rangecheck.go
@@ -1,4 +1,4 @@
-// Copyright 2018 Frank Schroeder. All rights reserved.
+// Copyright 2013-2022 Frank Schroeder. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/vendor/github.com/pelletier/go-toml/v2/.goreleaser.yaml b/vendor/github.com/pelletier/go-toml/v2/.goreleaser.yaml
index 793fb184..3aa1840e 100644
--- a/vendor/github.com/pelletier/go-toml/v2/.goreleaser.yaml
+++ b/vendor/github.com/pelletier/go-toml/v2/.goreleaser.yaml
@@ -16,7 +16,11 @@ builds:
mod_timestamp: '{{ .CommitTimestamp }}'
targets:
- linux_amd64
+ - linux_arm64
+ - linux_arm
- windows_amd64
+ - windows_arm64
+ - windows_arm
- darwin_amd64
- darwin_arm64
- id: tomljson
@@ -31,7 +35,11 @@ builds:
mod_timestamp: '{{ .CommitTimestamp }}'
targets:
- linux_amd64
+ - linux_arm64
+ - linux_arm
- windows_amd64
+ - windows_arm64
+ - windows_arm
- darwin_amd64
- darwin_arm64
- id: jsontoml
@@ -46,7 +54,11 @@ builds:
mod_timestamp: '{{ .CommitTimestamp }}'
targets:
- linux_amd64
+ - linux_arm64
+ - linux_arm
- windows_amd64
+ - windows_arm64
+ - windows_arm
- darwin_amd64
- darwin_arm64
universal_binaries:
diff --git a/vendor/github.com/pelletier/go-toml/v2/README.md b/vendor/github.com/pelletier/go-toml/v2/README.md
index a63c3a79..9f8439cc 100644
--- a/vendor/github.com/pelletier/go-toml/v2/README.md
+++ b/vendor/github.com/pelletier/go-toml/v2/README.md
@@ -140,6 +140,17 @@ fmt.Println(string(b))
[marshal]: https://pkg.go.dev/github.com/pelletier/go-toml/v2#Marshal
+## Unstable API
+
+This API does not yet follow the backward compatibility guarantees of this
+library. They provide early access to features that may have rough edges or an
+API subject to change.
+
+### Parser
+
+Parser is the unstable API that allows iterative parsing of a TOML document at
+the AST level. See https://pkg.go.dev/github.com/pelletier/go-toml/v2/unstable.
+
## Benchmarks
Execution time speedup compared to other Go TOML libraries:
diff --git a/vendor/github.com/pelletier/go-toml/v2/decode.go b/vendor/github.com/pelletier/go-toml/v2/decode.go
index 4af96536..3a860d0f 100644
--- a/vendor/github.com/pelletier/go-toml/v2/decode.go
+++ b/vendor/github.com/pelletier/go-toml/v2/decode.go
@@ -5,6 +5,8 @@ import (
"math"
"strconv"
"time"
+
+ "github.com/pelletier/go-toml/v2/unstable"
)
func parseInteger(b []byte) (int64, error) {
@@ -32,7 +34,7 @@ func parseLocalDate(b []byte) (LocalDate, error) {
var date LocalDate
if len(b) != 10 || b[4] != '-' || b[7] != '-' {
- return date, newDecodeError(b, "dates are expected to have the format YYYY-MM-DD")
+ return date, unstable.NewParserError(b, "dates are expected to have the format YYYY-MM-DD")
}
var err error
@@ -53,7 +55,7 @@ func parseLocalDate(b []byte) (LocalDate, error) {
}
if !isValidDate(date.Year, date.Month, date.Day) {
- return LocalDate{}, newDecodeError(b, "impossible date")
+ return LocalDate{}, unstable.NewParserError(b, "impossible date")
}
return date, nil
@@ -64,7 +66,7 @@ func parseDecimalDigits(b []byte) (int, error) {
for i, c := range b {
if c < '0' || c > '9' {
- return 0, newDecodeError(b[i:i+1], "expected digit (0-9)")
+ return 0, unstable.NewParserError(b[i:i+1], "expected digit (0-9)")
}
v *= 10
v += int(c - '0')
@@ -97,7 +99,7 @@ func parseDateTime(b []byte) (time.Time, error) {
} else {
const dateTimeByteLen = 6
if len(b) != dateTimeByteLen {
- return time.Time{}, newDecodeError(b, "invalid date-time timezone")
+ return time.Time{}, unstable.NewParserError(b, "invalid date-time timezone")
}
var direction int
switch b[0] {
@@ -106,11 +108,11 @@ func parseDateTime(b []byte) (time.Time, error) {
case '+':
direction = +1
default:
- return time.Time{}, newDecodeError(b[:1], "invalid timezone offset character")
+ return time.Time{}, unstable.NewParserError(b[:1], "invalid timezone offset character")
}
if b[3] != ':' {
- return time.Time{}, newDecodeError(b[3:4], "expected a : separator")
+ return time.Time{}, unstable.NewParserError(b[3:4], "expected a : separator")
}
hours, err := parseDecimalDigits(b[1:3])
@@ -118,7 +120,7 @@ func parseDateTime(b []byte) (time.Time, error) {
return time.Time{}, err
}
if hours > 23 {
- return time.Time{}, newDecodeError(b[:1], "invalid timezone offset hours")
+ return time.Time{}, unstable.NewParserError(b[:1], "invalid timezone offset hours")
}
minutes, err := parseDecimalDigits(b[4:6])
@@ -126,7 +128,7 @@ func parseDateTime(b []byte) (time.Time, error) {
return time.Time{}, err
}
if minutes > 59 {
- return time.Time{}, newDecodeError(b[:1], "invalid timezone offset minutes")
+ return time.Time{}, unstable.NewParserError(b[:1], "invalid timezone offset minutes")
}
seconds := direction * (hours*3600 + minutes*60)
@@ -139,7 +141,7 @@ func parseDateTime(b []byte) (time.Time, error) {
}
if len(b) > 0 {
- return time.Time{}, newDecodeError(b, "extra bytes at the end of the timezone")
+ return time.Time{}, unstable.NewParserError(b, "extra bytes at the end of the timezone")
}
t := time.Date(
@@ -160,7 +162,7 @@ func parseLocalDateTime(b []byte) (LocalDateTime, []byte, error) {
const localDateTimeByteMinLen = 11
if len(b) < localDateTimeByteMinLen {
- return dt, nil, newDecodeError(b, "local datetimes are expected to have the format YYYY-MM-DDTHH:MM:SS[.NNNNNNNNN]")
+ return dt, nil, unstable.NewParserError(b, "local datetimes are expected to have the format YYYY-MM-DDTHH:MM:SS[.NNNNNNNNN]")
}
date, err := parseLocalDate(b[:10])
@@ -171,7 +173,7 @@ func parseLocalDateTime(b []byte) (LocalDateTime, []byte, error) {
sep := b[10]
if sep != 'T' && sep != ' ' && sep != 't' {
- return dt, nil, newDecodeError(b[10:11], "datetime separator is expected to be T or a space")
+ return dt, nil, unstable.NewParserError(b[10:11], "datetime separator is expected to be T or a space")
}
t, rest, err := parseLocalTime(b[11:])
@@ -195,7 +197,7 @@ func parseLocalTime(b []byte) (LocalTime, []byte, error) {
// check if b matches to have expected format HH:MM:SS[.NNNNNN]
const localTimeByteLen = 8
if len(b) < localTimeByteLen {
- return t, nil, newDecodeError(b, "times are expected to have the format HH:MM:SS[.NNNNNN]")
+ return t, nil, unstable.NewParserError(b, "times are expected to have the format HH:MM:SS[.NNNNNN]")
}
var err error
@@ -206,10 +208,10 @@ func parseLocalTime(b []byte) (LocalTime, []byte, error) {
}
if t.Hour > 23 {
- return t, nil, newDecodeError(b[0:2], "hour cannot be greater 23")
+ return t, nil, unstable.NewParserError(b[0:2], "hour cannot be greater 23")
}
if b[2] != ':' {
- return t, nil, newDecodeError(b[2:3], "expecting colon between hours and minutes")
+ return t, nil, unstable.NewParserError(b[2:3], "expecting colon between hours and minutes")
}
t.Minute, err = parseDecimalDigits(b[3:5])
@@ -217,10 +219,10 @@ func parseLocalTime(b []byte) (LocalTime, []byte, error) {
return t, nil, err
}
if t.Minute > 59 {
- return t, nil, newDecodeError(b[3:5], "minutes cannot be greater 59")
+ return t, nil, unstable.NewParserError(b[3:5], "minutes cannot be greater 59")
}
if b[5] != ':' {
- return t, nil, newDecodeError(b[5:6], "expecting colon between minutes and seconds")
+ return t, nil, unstable.NewParserError(b[5:6], "expecting colon between minutes and seconds")
}
t.Second, err = parseDecimalDigits(b[6:8])
@@ -229,7 +231,7 @@ func parseLocalTime(b []byte) (LocalTime, []byte, error) {
}
if t.Second > 60 {
- return t, nil, newDecodeError(b[6:8], "seconds cannot be greater 60")
+ return t, nil, unstable.NewParserError(b[6:8], "seconds cannot be greater 60")
}
b = b[8:]
@@ -242,7 +244,7 @@ func parseLocalTime(b []byte) (LocalTime, []byte, error) {
for i, c := range b[1:] {
if !isDigit(c) {
if i == 0 {
- return t, nil, newDecodeError(b[0:1], "need at least one digit after fraction point")
+ return t, nil, unstable.NewParserError(b[0:1], "need at least one digit after fraction point")
}
break
}
@@ -266,7 +268,7 @@ func parseLocalTime(b []byte) (LocalTime, []byte, error) {
}
if precision == 0 {
- return t, nil, newDecodeError(b[:1], "nanoseconds need at least one digit")
+ return t, nil, unstable.NewParserError(b[:1], "nanoseconds need at least one digit")
}
t.Nanosecond = frac * nspow[precision]
@@ -289,24 +291,24 @@ func parseFloat(b []byte) (float64, error) {
}
if cleaned[0] == '.' {
- return 0, newDecodeError(b, "float cannot start with a dot")
+ return 0, unstable.NewParserError(b, "float cannot start with a dot")
}
if cleaned[len(cleaned)-1] == '.' {
- return 0, newDecodeError(b, "float cannot end with a dot")
+ return 0, unstable.NewParserError(b, "float cannot end with a dot")
}
dotAlreadySeen := false
for i, c := range cleaned {
if c == '.' {
if dotAlreadySeen {
- return 0, newDecodeError(b[i:i+1], "float can have at most one decimal point")
+ return 0, unstable.NewParserError(b[i:i+1], "float can have at most one decimal point")
}
if !isDigit(cleaned[i-1]) {
- return 0, newDecodeError(b[i-1:i+1], "float decimal point must be preceded by a digit")
+ return 0, unstable.NewParserError(b[i-1:i+1], "float decimal point must be preceded by a digit")
}
if !isDigit(cleaned[i+1]) {
- return 0, newDecodeError(b[i:i+2], "float decimal point must be followed by a digit")
+ return 0, unstable.NewParserError(b[i:i+2], "float decimal point must be followed by a digit")
}
dotAlreadySeen = true
}
@@ -317,12 +319,12 @@ func parseFloat(b []byte) (float64, error) {
start = 1
}
if cleaned[start] == '0' && isDigit(cleaned[start+1]) {
- return 0, newDecodeError(b, "float integer part cannot have leading zeroes")
+ return 0, unstable.NewParserError(b, "float integer part cannot have leading zeroes")
}
f, err := strconv.ParseFloat(string(cleaned), 64)
if err != nil {
- return 0, newDecodeError(b, "unable to parse float: %w", err)
+ return 0, unstable.NewParserError(b, "unable to parse float: %w", err)
}
return f, nil
@@ -336,7 +338,7 @@ func parseIntHex(b []byte) (int64, error) {
i, err := strconv.ParseInt(string(cleaned), 16, 64)
if err != nil {
- return 0, newDecodeError(b, "couldn't parse hexadecimal number: %w", err)
+ return 0, unstable.NewParserError(b, "couldn't parse hexadecimal number: %w", err)
}
return i, nil
@@ -350,7 +352,7 @@ func parseIntOct(b []byte) (int64, error) {
i, err := strconv.ParseInt(string(cleaned), 8, 64)
if err != nil {
- return 0, newDecodeError(b, "couldn't parse octal number: %w", err)
+ return 0, unstable.NewParserError(b, "couldn't parse octal number: %w", err)
}
return i, nil
@@ -364,7 +366,7 @@ func parseIntBin(b []byte) (int64, error) {
i, err := strconv.ParseInt(string(cleaned), 2, 64)
if err != nil {
- return 0, newDecodeError(b, "couldn't parse binary number: %w", err)
+ return 0, unstable.NewParserError(b, "couldn't parse binary number: %w", err)
}
return i, nil
@@ -387,12 +389,12 @@ func parseIntDec(b []byte) (int64, error) {
}
if len(cleaned) > startIdx+1 && cleaned[startIdx] == '0' {
- return 0, newDecodeError(b, "leading zero not allowed on decimal number")
+ return 0, unstable.NewParserError(b, "leading zero not allowed on decimal number")
}
i, err := strconv.ParseInt(string(cleaned), 10, 64)
if err != nil {
- return 0, newDecodeError(b, "couldn't parse decimal number: %w", err)
+ return 0, unstable.NewParserError(b, "couldn't parse decimal number: %w", err)
}
return i, nil
@@ -409,11 +411,11 @@ func checkAndRemoveUnderscoresIntegers(b []byte) ([]byte, error) {
}
if b[start] == '_' {
- return nil, newDecodeError(b[start:start+1], "number cannot start with underscore")
+ return nil, unstable.NewParserError(b[start:start+1], "number cannot start with underscore")
}
if b[len(b)-1] == '_' {
- return nil, newDecodeError(b[len(b)-1:], "number cannot end with underscore")
+ return nil, unstable.NewParserError(b[len(b)-1:], "number cannot end with underscore")
}
// fast path
@@ -435,7 +437,7 @@ func checkAndRemoveUnderscoresIntegers(b []byte) ([]byte, error) {
c := b[i]
if c == '_' {
if !before {
- return nil, newDecodeError(b[i-1:i+1], "number must have at least one digit between underscores")
+ return nil, unstable.NewParserError(b[i-1:i+1], "number must have at least one digit between underscores")
}
before = false
} else {
@@ -449,11 +451,11 @@ func checkAndRemoveUnderscoresIntegers(b []byte) ([]byte, error) {
func checkAndRemoveUnderscoresFloats(b []byte) ([]byte, error) {
if b[0] == '_' {
- return nil, newDecodeError(b[0:1], "number cannot start with underscore")
+ return nil, unstable.NewParserError(b[0:1], "number cannot start with underscore")
}
if b[len(b)-1] == '_' {
- return nil, newDecodeError(b[len(b)-1:], "number cannot end with underscore")
+ return nil, unstable.NewParserError(b[len(b)-1:], "number cannot end with underscore")
}
// fast path
@@ -476,10 +478,10 @@ func checkAndRemoveUnderscoresFloats(b []byte) ([]byte, error) {
switch c {
case '_':
if !before {
- return nil, newDecodeError(b[i-1:i+1], "number must have at least one digit between underscores")
+ return nil, unstable.NewParserError(b[i-1:i+1], "number must have at least one digit between underscores")
}
if i < len(b)-1 && (b[i+1] == 'e' || b[i+1] == 'E') {
- return nil, newDecodeError(b[i+1:i+2], "cannot have underscore before exponent")
+ return nil, unstable.NewParserError(b[i+1:i+2], "cannot have underscore before exponent")
}
before = false
case '+', '-':
@@ -488,15 +490,15 @@ func checkAndRemoveUnderscoresFloats(b []byte) ([]byte, error) {
before = false
case 'e', 'E':
if i < len(b)-1 && b[i+1] == '_' {
- return nil, newDecodeError(b[i+1:i+2], "cannot have underscore after exponent")
+ return nil, unstable.NewParserError(b[i+1:i+2], "cannot have underscore after exponent")
}
cleaned = append(cleaned, c)
case '.':
if i < len(b)-1 && b[i+1] == '_' {
- return nil, newDecodeError(b[i+1:i+2], "cannot have underscore after decimal point")
+ return nil, unstable.NewParserError(b[i+1:i+2], "cannot have underscore after decimal point")
}
if i > 0 && b[i-1] == '_' {
- return nil, newDecodeError(b[i-1:i], "cannot have underscore before decimal point")
+ return nil, unstable.NewParserError(b[i-1:i], "cannot have underscore before decimal point")
}
cleaned = append(cleaned, c)
default:
@@ -542,3 +544,7 @@ func daysIn(m int, year int) int {
func isLeap(year int) bool {
return year%4 == 0 && (year%100 != 0 || year%400 == 0)
}
+
+func isDigit(r byte) bool {
+ return r >= '0' && r <= '9'
+}
diff --git a/vendor/github.com/pelletier/go-toml/v2/errors.go b/vendor/github.com/pelletier/go-toml/v2/errors.go
index 5e6635c3..309733f1 100644
--- a/vendor/github.com/pelletier/go-toml/v2/errors.go
+++ b/vendor/github.com/pelletier/go-toml/v2/errors.go
@@ -6,6 +6,7 @@ import (
"strings"
"github.com/pelletier/go-toml/v2/internal/danger"
+ "github.com/pelletier/go-toml/v2/unstable"
)
// DecodeError represents an error encountered during the parsing or decoding
@@ -55,25 +56,6 @@ func (s *StrictMissingError) String() string {
type Key []string
-// internal version of DecodeError that is used as the base to create a
-// DecodeError with full context.
-type decodeError struct {
- highlight []byte
- message string
- key Key // optional
-}
-
-func (de *decodeError) Error() string {
- return de.message
-}
-
-func newDecodeError(highlight []byte, format string, args ...interface{}) error {
- return &decodeError{
- highlight: highlight,
- message: fmt.Errorf(format, args...).Error(),
- }
-}
-
// Error returns the error message contained in the DecodeError.
func (e *DecodeError) Error() string {
return "toml: " + e.message
@@ -103,13 +85,14 @@ func (e *DecodeError) Key() Key {
//
// The function copies all bytes used in DecodeError, so that document and
// highlight can be freely deallocated.
+//
//nolint:funlen
-func wrapDecodeError(document []byte, de *decodeError) *DecodeError {
- offset := danger.SubsliceOffset(document, de.highlight)
+func wrapDecodeError(document []byte, de *unstable.ParserError) *DecodeError {
+ offset := danger.SubsliceOffset(document, de.Highlight)
errMessage := de.Error()
errLine, errColumn := positionAtEnd(document[:offset])
- before, after := linesOfContext(document, de.highlight, offset, 3)
+ before, after := linesOfContext(document, de.Highlight, offset, 3)
var buf strings.Builder
@@ -139,7 +122,7 @@ func wrapDecodeError(document []byte, de *decodeError) *DecodeError {
buf.Write(before[0])
}
- buf.Write(de.highlight)
+ buf.Write(de.Highlight)
if len(after) > 0 {
buf.Write(after[0])
@@ -157,7 +140,7 @@ func wrapDecodeError(document []byte, de *decodeError) *DecodeError {
buf.WriteString(strings.Repeat(" ", len(before[0])))
}
- buf.WriteString(strings.Repeat("~", len(de.highlight)))
+ buf.WriteString(strings.Repeat("~", len(de.Highlight)))
if len(errMessage) > 0 {
buf.WriteString(" ")
@@ -182,7 +165,7 @@ func wrapDecodeError(document []byte, de *decodeError) *DecodeError {
message: errMessage,
line: errLine,
column: errColumn,
- key: de.key,
+ key: de.Key,
human: buf.String(),
}
}
diff --git a/vendor/github.com/pelletier/go-toml/v2/internal/ast/builder.go b/vendor/github.com/pelletier/go-toml/v2/internal/ast/builder.go
deleted file mode 100644
index 120f16e5..00000000
--- a/vendor/github.com/pelletier/go-toml/v2/internal/ast/builder.go
+++ /dev/null
@@ -1,51 +0,0 @@
-package ast
-
-type Reference int
-
-const InvalidReference Reference = -1
-
-func (r Reference) Valid() bool {
- return r != InvalidReference
-}
-
-type Builder struct {
- tree Root
- lastIdx int
-}
-
-func (b *Builder) Tree() *Root {
- return &b.tree
-}
-
-func (b *Builder) NodeAt(ref Reference) *Node {
- return b.tree.at(ref)
-}
-
-func (b *Builder) Reset() {
- b.tree.nodes = b.tree.nodes[:0]
- b.lastIdx = 0
-}
-
-func (b *Builder) Push(n Node) Reference {
- b.lastIdx = len(b.tree.nodes)
- b.tree.nodes = append(b.tree.nodes, n)
- return Reference(b.lastIdx)
-}
-
-func (b *Builder) PushAndChain(n Node) Reference {
- newIdx := len(b.tree.nodes)
- b.tree.nodes = append(b.tree.nodes, n)
- if b.lastIdx >= 0 {
- b.tree.nodes[b.lastIdx].next = newIdx - b.lastIdx
- }
- b.lastIdx = newIdx
- return Reference(b.lastIdx)
-}
-
-func (b *Builder) AttachChild(parent Reference, child Reference) {
- b.tree.nodes[parent].child = int(child) - int(parent)
-}
-
-func (b *Builder) Chain(from Reference, to Reference) {
- b.tree.nodes[from].next = int(to) - int(from)
-}
diff --git a/vendor/github.com/pelletier/go-toml/v2/internal/characters/ascii.go b/vendor/github.com/pelletier/go-toml/v2/internal/characters/ascii.go
new file mode 100644
index 00000000..80f698db
--- /dev/null
+++ b/vendor/github.com/pelletier/go-toml/v2/internal/characters/ascii.go
@@ -0,0 +1,42 @@
+package characters
+
+var invalidAsciiTable = [256]bool{
+ 0x00: true,
+ 0x01: true,
+ 0x02: true,
+ 0x03: true,
+ 0x04: true,
+ 0x05: true,
+ 0x06: true,
+ 0x07: true,
+ 0x08: true,
+ // 0x09 TAB
+ // 0x0A LF
+ 0x0B: true,
+ 0x0C: true,
+ // 0x0D CR
+ 0x0E: true,
+ 0x0F: true,
+ 0x10: true,
+ 0x11: true,
+ 0x12: true,
+ 0x13: true,
+ 0x14: true,
+ 0x15: true,
+ 0x16: true,
+ 0x17: true,
+ 0x18: true,
+ 0x19: true,
+ 0x1A: true,
+ 0x1B: true,
+ 0x1C: true,
+ 0x1D: true,
+ 0x1E: true,
+ 0x1F: true,
+ // 0x20 - 0x7E Printable ASCII characters
+ 0x7F: true,
+}
+
+func InvalidAscii(b byte) bool {
+ return invalidAsciiTable[b]
+}
diff --git a/vendor/github.com/pelletier/go-toml/v2/utf8.go b/vendor/github.com/pelletier/go-toml/v2/internal/characters/utf8.go
index d47a4f20..db4f45ac 100644
--- a/vendor/github.com/pelletier/go-toml/v2/utf8.go
+++ b/vendor/github.com/pelletier/go-toml/v2/internal/characters/utf8.go
@@ -1,4 +1,4 @@
-package toml
+package characters
import (
"unicode/utf8"
@@ -32,7 +32,7 @@ func (u utf8Err) Zero() bool {
// 0x9 => tab, ok
// 0xA - 0x1F => invalid
// 0x7F => invalid
-func utf8TomlValidAlreadyEscaped(p []byte) (err utf8Err) {
+func Utf8TomlValidAlreadyEscaped(p []byte) (err utf8Err) {
// Fast path. Check for and skip 8 bytes of ASCII characters per iteration.
offset := 0
for len(p) >= 8 {
@@ -48,7 +48,7 @@ func utf8TomlValidAlreadyEscaped(p []byte) (err utf8Err) {
}
for i, b := range p[:8] {
- if invalidAscii(b) {
+ if InvalidAscii(b) {
err.Index = offset + i
err.Size = 1
return
@@ -62,7 +62,7 @@ func utf8TomlValidAlreadyEscaped(p []byte) (err utf8Err) {
for i := 0; i < n; {
pi := p[i]
if pi < utf8.RuneSelf {
- if invalidAscii(pi) {
+ if InvalidAscii(pi) {
err.Index = offset + i
err.Size = 1
return
@@ -106,11 +106,11 @@ func utf8TomlValidAlreadyEscaped(p []byte) (err utf8Err) {
}
// Return the size of the next rune if valid, 0 otherwise.
-func utf8ValidNext(p []byte) int {
+func Utf8ValidNext(p []byte) int {
c := p[0]
if c < utf8.RuneSelf {
- if invalidAscii(c) {
+ if InvalidAscii(c) {
return 0
}
return 1
@@ -140,47 +140,6 @@ func utf8ValidNext(p []byte) int {
return size
}
-var invalidAsciiTable = [256]bool{
- 0x00: true,
- 0x01: true,
- 0x02: true,
- 0x03: true,
- 0x04: true,
- 0x05: true,
- 0x06: true,
- 0x07: true,
- 0x08: true,
- // 0x09 TAB
- // 0x0A LF
- 0x0B: true,
- 0x0C: true,
- // 0x0D CR
- 0x0E: true,
- 0x0F: true,
- 0x10: true,
- 0x11: true,
- 0x12: true,
- 0x13: true,
- 0x14: true,
- 0x15: true,
- 0x16: true,
- 0x17: true,
- 0x18: true,
- 0x19: true,
- 0x1A: true,
- 0x1B: true,
- 0x1C: true,
- 0x1D: true,
- 0x1E: true,
- 0x1F: true,
- // 0x20 - 0x7E Printable ASCII characters
- 0x7F: true,
-}
-
-func invalidAscii(b byte) bool {
- return invalidAsciiTable[b]
-}
-
// acceptRange gives the range of valid values for the second byte in a UTF-8
// sequence.
type acceptRange struct {
diff --git a/vendor/github.com/pelletier/go-toml/v2/internal/tracker/key.go b/vendor/github.com/pelletier/go-toml/v2/internal/tracker/key.go
index 7c148f48..149b17f5 100644
--- a/vendor/github.com/pelletier/go-toml/v2/internal/tracker/key.go
+++ b/vendor/github.com/pelletier/go-toml/v2/internal/tracker/key.go
@@ -1,8 +1,6 @@
package tracker
-import (
- "github.com/pelletier/go-toml/v2/internal/ast"
-)
+import "github.com/pelletier/go-toml/v2/unstable"
// KeyTracker is a tracker that keeps track of the current Key as the AST is
// walked.
@@ -11,19 +9,19 @@ type KeyTracker struct {
}
// UpdateTable sets the state of the tracker with the AST table node.
-func (t *KeyTracker) UpdateTable(node *ast.Node) {
+func (t *KeyTracker) UpdateTable(node *unstable.Node) {
t.reset()
t.Push(node)
}
// UpdateArrayTable sets the state of the tracker with the AST array table node.
-func (t *KeyTracker) UpdateArrayTable(node *ast.Node) {
+func (t *KeyTracker) UpdateArrayTable(node *unstable.Node) {
t.reset()
t.Push(node)
}
// Push the given key on the stack.
-func (t *KeyTracker) Push(node *ast.Node) {
+func (t *KeyTracker) Push(node *unstable.Node) {
it := node.Key()
for it.Next() {
t.k = append(t.k, string(it.Node().Data))
@@ -31,7 +29,7 @@ func (t *KeyTracker) Push(node *ast.Node) {
}
// Pop key from stack.
-func (t *KeyTracker) Pop(node *ast.Node) {
+func (t *KeyTracker) Pop(node *unstable.Node) {
it := node.Key()
for it.Next() {
t.k = t.k[:len(t.k)-1]
diff --git a/vendor/github.com/pelletier/go-toml/v2/internal/tracker/seen.go b/vendor/github.com/pelletier/go-toml/v2/internal/tracker/seen.go
index a7ee05ba..40e23f83 100644
--- a/vendor/github.com/pelletier/go-toml/v2/internal/tracker/seen.go
+++ b/vendor/github.com/pelletier/go-toml/v2/internal/tracker/seen.go
@@ -5,7 +5,7 @@ import (
"fmt"
"sync"
- "github.com/pelletier/go-toml/v2/internal/ast"
+ "github.com/pelletier/go-toml/v2/unstable"
)
type keyKind uint8
@@ -150,23 +150,23 @@ func (s *SeenTracker) setExplicitFlag(parentIdx int) {
// CheckExpression takes a top-level node and checks that it does not contain
// keys that have been seen in previous calls, and validates that types are
// consistent.
-func (s *SeenTracker) CheckExpression(node *ast.Node) error {
+func (s *SeenTracker) CheckExpression(node *unstable.Node) error {
if s.entries == nil {
s.reset()
}
switch node.Kind {
- case ast.KeyValue:
+ case unstable.KeyValue:
return s.checkKeyValue(node)
- case ast.Table:
+ case unstable.Table:
return s.checkTable(node)
- case ast.ArrayTable:
+ case unstable.ArrayTable:
return s.checkArrayTable(node)
default:
panic(fmt.Errorf("this should not be a top level node type: %s", node.Kind))
}
}
-func (s *SeenTracker) checkTable(node *ast.Node) error {
+func (s *SeenTracker) checkTable(node *unstable.Node) error {
if s.currentIdx >= 0 {
s.setExplicitFlag(s.currentIdx)
}
@@ -219,7 +219,7 @@ func (s *SeenTracker) checkTable(node *ast.Node) error {
return nil
}
-func (s *SeenTracker) checkArrayTable(node *ast.Node) error {
+func (s *SeenTracker) checkArrayTable(node *unstable.Node) error {
if s.currentIdx >= 0 {
s.setExplicitFlag(s.currentIdx)
}
@@ -267,7 +267,7 @@ func (s *SeenTracker) checkArrayTable(node *ast.Node) error {
return nil
}
-func (s *SeenTracker) checkKeyValue(node *ast.Node) error {
+func (s *SeenTracker) checkKeyValue(node *unstable.Node) error {
parentIdx := s.currentIdx
it := node.Key()
@@ -297,26 +297,26 @@ func (s *SeenTracker) checkKeyValue(node *ast.Node) error {
value := node.Value()
switch value.Kind {
- case ast.InlineTable:
+ case unstable.InlineTable:
return s.checkInlineTable(value)
- case ast.Array:
+ case unstable.Array:
return s.checkArray(value)
}
return nil
}
-func (s *SeenTracker) checkArray(node *ast.Node) error {
+func (s *SeenTracker) checkArray(node *unstable.Node) error {
it := node.Children()
for it.Next() {
n := it.Node()
switch n.Kind {
- case ast.InlineTable:
+ case unstable.InlineTable:
err := s.checkInlineTable(n)
if err != nil {
return err
}
- case ast.Array:
+ case unstable.Array:
err := s.checkArray(n)
if err != nil {
return err
@@ -326,7 +326,7 @@ func (s *SeenTracker) checkArray(node *ast.Node) error {
return nil
}
-func (s *SeenTracker) checkInlineTable(node *ast.Node) error {
+func (s *SeenTracker) checkInlineTable(node *unstable.Node) error {
if pool.New == nil {
pool.New = func() interface{} {
return &SeenTracker{}
diff --git a/vendor/github.com/pelletier/go-toml/v2/localtime.go b/vendor/github.com/pelletier/go-toml/v2/localtime.go
index 30a31dcb..a856bfdb 100644
--- a/vendor/github.com/pelletier/go-toml/v2/localtime.go
+++ b/vendor/github.com/pelletier/go-toml/v2/localtime.go
@@ -4,6 +4,8 @@ import (
"fmt"
"strings"
"time"
+
+ "github.com/pelletier/go-toml/v2/unstable"
)
// LocalDate represents a calendar day in no specific timezone.
@@ -75,7 +77,7 @@ func (d LocalTime) MarshalText() ([]byte, error) {
func (d *LocalTime) UnmarshalText(b []byte) error {
res, left, err := parseLocalTime(b)
if err == nil && len(left) != 0 {
- err = newDecodeError(left, "extra characters")
+ err = unstable.NewParserError(left, "extra characters")
}
if err != nil {
return err
@@ -109,7 +111,7 @@ func (d LocalDateTime) MarshalText() ([]byte, error) {
func (d *LocalDateTime) UnmarshalText(data []byte) error {
res, left, err := parseLocalDateTime(data)
if err == nil && len(left) != 0 {
- err = newDecodeError(left, "extra characters")
+ err = unstable.NewParserError(left, "extra characters")
}
if err != nil {
return err
diff --git a/vendor/github.com/pelletier/go-toml/v2/marshaler.go b/vendor/github.com/pelletier/go-toml/v2/marshaler.go
index c14c1cea..07aceb90 100644
--- a/vendor/github.com/pelletier/go-toml/v2/marshaler.go
+++ b/vendor/github.com/pelletier/go-toml/v2/marshaler.go
@@ -12,6 +12,8 @@ import (
"strings"
"time"
"unicode"
+
+ "github.com/pelletier/go-toml/v2/internal/characters"
)
// Marshal serializes a Go value as a TOML document.
@@ -54,7 +56,7 @@ func NewEncoder(w io.Writer) *Encoder {
// This behavior can be controlled on an individual struct field basis with the
// inline tag:
//
-// MyField `inline:"true"`
+// MyField `toml:",inline"`
func (enc *Encoder) SetTablesInline(inline bool) *Encoder {
enc.tablesInline = inline
return enc
@@ -65,7 +67,7 @@ func (enc *Encoder) SetTablesInline(inline bool) *Encoder {
//
// This behavior can be controlled on an individual struct field basis with the multiline tag:
//
-// MyField `multiline:"true"`
+// MyField `multiline:"true"`
func (enc *Encoder) SetArraysMultiline(multiline bool) *Encoder {
enc.arraysMultiline = multiline
return enc
@@ -89,7 +91,7 @@ func (enc *Encoder) SetIndentTables(indent bool) *Encoder {
//
// If v cannot be represented to TOML it returns an error.
//
-// Encoding rules
+// # Encoding rules
//
// A top level slice containing only maps or structs is encoded as [[table
// array]].
@@ -107,10 +109,30 @@ func (enc *Encoder) SetIndentTables(indent bool) *Encoder {
// a newline character or a single quote. In that case they are emitted as
// quoted strings.
//
+// Unsigned integers larger than math.MaxInt64 cannot be encoded. Doing so
+// results in an error. This rule exists because the TOML specification only
+// requires parsers to support at least the 64 bits integer range. Allowing
+// larger numbers would create non-standard TOML documents, which may not be
+// readable (at best) by other implementations. To encode such numbers, a
+// solution is a custom type that implements encoding.TextMarshaler.
+//
// When encoding structs, fields are encoded in order of definition, with their
// exact name.
//
-// Struct tags
+// Tables and array tables are separated by empty lines. However, consecutive
+// subtables definitions are not. For example:
+//
+// [top1]
+//
+// [top2]
+// [top2.child1]
+//
+// [[array]]
+//
+// [[array]]
+// [array.child2]
+//
+// # Struct tags
//
// The encoding of each public struct field can be customized by the format
// string in the "toml" key of the struct field's tag. This follows
@@ -303,7 +325,11 @@ func (enc *Encoder) encode(b []byte, ctx encoderCtx, v reflect.Value) ([]byte, e
b = append(b, "false"...)
}
case reflect.Uint64, reflect.Uint32, reflect.Uint16, reflect.Uint8, reflect.Uint:
- b = strconv.AppendUint(b, v.Uint(), 10)
+ x := v.Uint()
+ if x > uint64(math.MaxInt64) {
+ return nil, fmt.Errorf("toml: not encoding uint (%d) greater than max int64 (%d)", x, int64(math.MaxInt64))
+ }
+ b = strconv.AppendUint(b, x, 10)
case reflect.Int64, reflect.Int32, reflect.Int16, reflect.Int8, reflect.Int:
b = strconv.AppendInt(b, v.Int(), 10)
default:
@@ -322,13 +348,13 @@ func isNil(v reflect.Value) bool {
}
}
+func shouldOmitEmpty(options valueOptions, v reflect.Value) bool {
+ return options.omitempty && isEmptyValue(v)
+}
+
func (enc *Encoder) encodeKv(b []byte, ctx encoderCtx, options valueOptions, v reflect.Value) ([]byte, error) {
var err error
- if (ctx.options.omitempty || options.omitempty) && isEmptyValue(v) {
- return b, nil
- }
-
if !ctx.inline {
b = enc.encodeComment(ctx.indent, options.comment, b)
}
@@ -354,6 +380,8 @@ func (enc *Encoder) encodeKv(b []byte, ctx encoderCtx, options valueOptions, v r
func isEmptyValue(v reflect.Value) bool {
switch v.Kind() {
+ case reflect.Struct:
+ return isEmptyStruct(v)
case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
return v.Len() == 0
case reflect.Bool:
@@ -370,6 +398,34 @@ func isEmptyValue(v reflect.Value) bool {
return false
}
+func isEmptyStruct(v reflect.Value) bool {
+ // TODO: merge with walkStruct and cache.
+ typ := v.Type()
+ for i := 0; i < typ.NumField(); i++ {
+ fieldType := typ.Field(i)
+
+ // only consider exported fields
+ if fieldType.PkgPath != "" {
+ continue
+ }
+
+ tag := fieldType.Tag.Get("toml")
+
+ // special field name to skip field
+ if tag == "-" {
+ continue
+ }
+
+ f := v.Field(i)
+
+ if !isEmptyValue(f) {
+ return false
+ }
+ }
+
+ return true
+}
+
const literalQuote = '\''
func (enc *Encoder) encodeString(b []byte, v string, options valueOptions) []byte {
@@ -383,7 +439,7 @@ func (enc *Encoder) encodeString(b []byte, v string, options valueOptions) []byt
func needsQuoting(v string) bool {
// TODO: vectorize
for _, b := range []byte(v) {
- if b == '\'' || b == '\r' || b == '\n' || invalidAscii(b) {
+ if b == '\'' || b == '\r' || b == '\n' || characters.InvalidAscii(b) {
return true
}
}
@@ -399,7 +455,6 @@ func (enc *Encoder) encodeLiteralString(b []byte, v string) []byte {
return b
}
-//nolint:cyclop
func (enc *Encoder) encodeQuotedString(multiline bool, b []byte, v string) []byte {
stringQuote := `"`
@@ -746,7 +801,13 @@ func (enc *Encoder) encodeTable(b []byte, ctx encoderCtx, t table) ([]byte, erro
}
ctx.skipTableHeader = false
+ hasNonEmptyKV := false
for _, kv := range t.kvs {
+ if shouldOmitEmpty(kv.Options, kv.Value) {
+ continue
+ }
+ hasNonEmptyKV = true
+
ctx.setKey(kv.Key)
b, err = enc.encodeKv(b, ctx, kv.Options, kv.Value)
@@ -757,7 +818,20 @@ func (enc *Encoder) encodeTable(b []byte, ctx encoderCtx, t table) ([]byte, erro
b = append(b, '\n')
}
+ first := true
for _, table := range t.tables {
+ if shouldOmitEmpty(table.Options, table.Value) {
+ continue
+ }
+ if first {
+ first = false
+ if hasNonEmptyKV {
+ b = append(b, '\n')
+ }
+ } else {
+ b = append(b, "\n"...)
+ }
+
ctx.setKey(table.Key)
ctx.options = table.Options
@@ -766,8 +840,6 @@ func (enc *Encoder) encodeTable(b []byte, ctx encoderCtx, t table) ([]byte, erro
if err != nil {
return nil, err
}
-
- b = append(b, '\n')
}
return b, nil
@@ -780,6 +852,10 @@ func (enc *Encoder) encodeTableInline(b []byte, ctx encoderCtx, t table) ([]byte
first := true
for _, kv := range t.kvs {
+ if shouldOmitEmpty(kv.Options, kv.Value) {
+ continue
+ }
+
if first {
first = false
} else {
@@ -795,7 +871,7 @@ func (enc *Encoder) encodeTableInline(b []byte, ctx encoderCtx, t table) ([]byte
}
if len(t.tables) > 0 {
- panic("inline table cannot contain nested tables, online key-values")
+ panic("inline table cannot contain nested tables, only key-values")
}
b = append(b, "}"...)
@@ -894,6 +970,10 @@ func (enc *Encoder) encodeSliceAsArrayTable(b []byte, ctx encoderCtx, v reflect.
b = enc.encodeComment(ctx.indent, ctx.options.comment, b)
for i := 0; i < v.Len(); i++ {
+ if i != 0 {
+ b = append(b, "\n"...)
+ }
+
b = append(b, scratch...)
var err error
diff --git a/vendor/github.com/pelletier/go-toml/v2/strict.go b/vendor/github.com/pelletier/go-toml/v2/strict.go
index b7830d13..802e7e4d 100644
--- a/vendor/github.com/pelletier/go-toml/v2/strict.go
+++ b/vendor/github.com/pelletier/go-toml/v2/strict.go
@@ -1,9 +1,9 @@
package toml
import (
- "github.com/pelletier/go-toml/v2/internal/ast"
"github.com/pelletier/go-toml/v2/internal/danger"
"github.com/pelletier/go-toml/v2/internal/tracker"
+ "github.com/pelletier/go-toml/v2/unstable"
)
type strict struct {
@@ -12,10 +12,10 @@ type strict struct {
// Tracks the current key being processed.
key tracker.KeyTracker
- missing []decodeError
+ missing []unstable.ParserError
}
-func (s *strict) EnterTable(node *ast.Node) {
+func (s *strict) EnterTable(node *unstable.Node) {
if !s.Enabled {
return
}
@@ -23,7 +23,7 @@ func (s *strict) EnterTable(node *ast.Node) {
s.key.UpdateTable(node)
}
-func (s *strict) EnterArrayTable(node *ast.Node) {
+func (s *strict) EnterArrayTable(node *unstable.Node) {
if !s.Enabled {
return
}
@@ -31,7 +31,7 @@ func (s *strict) EnterArrayTable(node *ast.Node) {
s.key.UpdateArrayTable(node)
}
-func (s *strict) EnterKeyValue(node *ast.Node) {
+func (s *strict) EnterKeyValue(node *unstable.Node) {
if !s.Enabled {
return
}
@@ -39,7 +39,7 @@ func (s *strict) EnterKeyValue(node *ast.Node) {
s.key.Push(node)
}
-func (s *strict) ExitKeyValue(node *ast.Node) {
+func (s *strict) ExitKeyValue(node *unstable.Node) {
if !s.Enabled {
return
}
@@ -47,27 +47,27 @@ func (s *strict) ExitKeyValue(node *ast.Node) {
s.key.Pop(node)
}
-func (s *strict) MissingTable(node *ast.Node) {
+func (s *strict) MissingTable(node *unstable.Node) {
if !s.Enabled {
return
}
- s.missing = append(s.missing, decodeError{
- highlight: keyLocation(node),
- message: "missing table",
- key: s.key.Key(),
+ s.missing = append(s.missing, unstable.ParserError{
+ Highlight: keyLocation(node),
+ Message: "missing table",
+ Key: s.key.Key(),
})
}
-func (s *strict) MissingField(node *ast.Node) {
+func (s *strict) MissingField(node *unstable.Node) {
if !s.Enabled {
return
}
- s.missing = append(s.missing, decodeError{
- highlight: keyLocation(node),
- message: "missing field",
- key: s.key.Key(),
+ s.missing = append(s.missing, unstable.ParserError{
+ Highlight: keyLocation(node),
+ Message: "missing field",
+ Key: s.key.Key(),
})
}
@@ -88,7 +88,7 @@ func (s *strict) Error(doc []byte) error {
return err
}
-func keyLocation(node *ast.Node) []byte {
+func keyLocation(node *unstable.Node) []byte {
k := node.Key()
hasOne := k.Next()
diff --git a/vendor/github.com/pelletier/go-toml/v2/types.go b/vendor/github.com/pelletier/go-toml/v2/types.go
index 630a4546..3c6b8fe5 100644
--- a/vendor/github.com/pelletier/go-toml/v2/types.go
+++ b/vendor/github.com/pelletier/go-toml/v2/types.go
@@ -6,9 +6,9 @@ import (
"time"
)
-var timeType = reflect.TypeOf(time.Time{})
-var textMarshalerType = reflect.TypeOf(new(encoding.TextMarshaler)).Elem()
-var textUnmarshalerType = reflect.TypeOf(new(encoding.TextUnmarshaler)).Elem()
-var mapStringInterfaceType = reflect.TypeOf(map[string]interface{}{})
-var sliceInterfaceType = reflect.TypeOf([]interface{}{})
+var timeType = reflect.TypeOf((*time.Time)(nil)).Elem()
+var textMarshalerType = reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem()
+var textUnmarshalerType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem()
+var mapStringInterfaceType = reflect.TypeOf(map[string]interface{}(nil))
+var sliceInterfaceType = reflect.TypeOf([]interface{}(nil))
var stringType = reflect.TypeOf("")
diff --git a/vendor/github.com/pelletier/go-toml/v2/unmarshaler.go b/vendor/github.com/pelletier/go-toml/v2/unmarshaler.go
index b3596f6d..70f6ec57 100644
--- a/vendor/github.com/pelletier/go-toml/v2/unmarshaler.go
+++ b/vendor/github.com/pelletier/go-toml/v2/unmarshaler.go
@@ -12,16 +12,16 @@ import (
"sync/atomic"
"time"
- "github.com/pelletier/go-toml/v2/internal/ast"
"github.com/pelletier/go-toml/v2/internal/danger"
"github.com/pelletier/go-toml/v2/internal/tracker"
+ "github.com/pelletier/go-toml/v2/unstable"
)
// Unmarshal deserializes a TOML document into a Go value.
//
// It is a shortcut for Decoder.Decode() with the default options.
func Unmarshal(data []byte, v interface{}) error {
- p := parser{}
+ p := unstable.Parser{}
p.Reset(data)
d := decoder{p: &p}
@@ -79,29 +79,29 @@ func (d *Decoder) DisallowUnknownFields() *Decoder {
// strict mode and a field is missing, a `toml.StrictMissingError` is
// returned. In any other case, this function returns a standard Go error.
//
-// Type mapping
+// # Type mapping
//
// List of supported TOML types and their associated accepted Go types:
//
-// String -> string
-// Integer -> uint*, int*, depending on size
-// Float -> float*, depending on size
-// Boolean -> bool
-// Offset Date-Time -> time.Time
-// Local Date-time -> LocalDateTime, time.Time
-// Local Date -> LocalDate, time.Time
-// Local Time -> LocalTime, time.Time
-// Array -> slice and array, depending on elements types
-// Table -> map and struct
-// Inline Table -> same as Table
-// Array of Tables -> same as Array and Table
+// String -> string
+// Integer -> uint*, int*, depending on size
+// Float -> float*, depending on size
+// Boolean -> bool
+// Offset Date-Time -> time.Time
+// Local Date-time -> LocalDateTime, time.Time
+// Local Date -> LocalDate, time.Time
+// Local Time -> LocalTime, time.Time
+// Array -> slice and array, depending on elements types
+// Table -> map and struct
+// Inline Table -> same as Table
+// Array of Tables -> same as Array and Table
func (d *Decoder) Decode(v interface{}) error {
b, err := ioutil.ReadAll(d.r)
if err != nil {
return fmt.Errorf("toml: %w", err)
}
- p := parser{}
+ p := unstable.Parser{}
p.Reset(b)
dec := decoder{
p: &p,
@@ -115,7 +115,7 @@ func (d *Decoder) Decode(v interface{}) error {
type decoder struct {
// Which parser instance in use for this decoding session.
- p *parser
+ p *unstable.Parser
// Flag indicating that the current expression is stashed.
// If set to true, calling nextExpr will not actually pull a new expression
@@ -123,7 +123,7 @@ type decoder struct {
stashedExpr bool
// Skip expressions until a table is found. This is set to true when a
- // table could not be create (missing field in map), so all KV expressions
+ // table could not be created (missing field in map), so all KV expressions
// need to be skipped.
skipUntilTable bool
@@ -157,7 +157,7 @@ func (d *decoder) typeMismatchError(toml string, target reflect.Type) error {
return fmt.Errorf("toml: cannot decode TOML %s into a Go value of type %s", toml, target)
}
-func (d *decoder) expr() *ast.Node {
+func (d *decoder) expr() *unstable.Node {
return d.p.Expression()
}
@@ -208,12 +208,12 @@ func (d *decoder) FromParser(v interface{}) error {
err := d.fromParser(r)
if err == nil {
- return d.strict.Error(d.p.data)
+ return d.strict.Error(d.p.Data())
}
- var e *decodeError
+ var e *unstable.ParserError
if errors.As(err, &e) {
- return wrapDecodeError(d.p.data, e)
+ return wrapDecodeError(d.p.Data(), e)
}
return err
@@ -234,16 +234,16 @@ func (d *decoder) fromParser(root reflect.Value) error {
Rules for the unmarshal code:
- The stack is used to keep track of which values need to be set where.
-- handle* functions <=> switch on a given ast.Kind.
+- handle* functions <=> switch on a given unstable.Kind.
- unmarshalX* functions need to unmarshal a node of kind X.
- An "object" is either a struct or a map.
*/
-func (d *decoder) handleRootExpression(expr *ast.Node, v reflect.Value) error {
+func (d *decoder) handleRootExpression(expr *unstable.Node, v reflect.Value) error {
var x reflect.Value
var err error
- if !(d.skipUntilTable && expr.Kind == ast.KeyValue) {
+ if !(d.skipUntilTable && expr.Kind == unstable.KeyValue) {
err = d.seen.CheckExpression(expr)
if err != nil {
return err
@@ -251,16 +251,16 @@ func (d *decoder) handleRootExpression(expr *ast.Node, v reflect.Value) error {
}
switch expr.Kind {
- case ast.KeyValue:
+ case unstable.KeyValue:
if d.skipUntilTable {
return nil
}
x, err = d.handleKeyValue(expr, v)
- case ast.Table:
+ case unstable.Table:
d.skipUntilTable = false
d.strict.EnterTable(expr)
x, err = d.handleTable(expr.Key(), v)
- case ast.ArrayTable:
+ case unstable.ArrayTable:
d.skipUntilTable = false
d.strict.EnterArrayTable(expr)
x, err = d.handleArrayTable(expr.Key(), v)
@@ -269,7 +269,7 @@ func (d *decoder) handleRootExpression(expr *ast.Node, v reflect.Value) error {
}
if d.skipUntilTable {
- if expr.Kind == ast.Table || expr.Kind == ast.ArrayTable {
+ if expr.Kind == unstable.Table || expr.Kind == unstable.ArrayTable {
d.strict.MissingTable(expr)
}
} else if err == nil && x.IsValid() {
@@ -279,14 +279,14 @@ func (d *decoder) handleRootExpression(expr *ast.Node, v reflect.Value) error {
return err
}
-func (d *decoder) handleArrayTable(key ast.Iterator, v reflect.Value) (reflect.Value, error) {
+func (d *decoder) handleArrayTable(key unstable.Iterator, v reflect.Value) (reflect.Value, error) {
if key.Next() {
return d.handleArrayTablePart(key, v)
}
return d.handleKeyValues(v)
}
-func (d *decoder) handleArrayTableCollectionLast(key ast.Iterator, v reflect.Value) (reflect.Value, error) {
+func (d *decoder) handleArrayTableCollectionLast(key unstable.Iterator, v reflect.Value) (reflect.Value, error) {
switch v.Kind() {
case reflect.Interface:
elem := v.Elem()
@@ -339,21 +339,21 @@ func (d *decoder) handleArrayTableCollectionLast(key ast.Iterator, v reflect.Val
case reflect.Array:
idx := d.arrayIndex(true, v)
if idx >= v.Len() {
- return v, fmt.Errorf("toml: cannot decode array table into %s at position %d", v.Type(), idx)
+ return v, fmt.Errorf("%s at position %d", d.typeMismatchError("array table", v.Type()), idx)
}
elem := v.Index(idx)
_, err := d.handleArrayTable(key, elem)
return v, err
+ default:
+ return reflect.Value{}, d.typeMismatchError("array table", v.Type())
}
-
- return d.handleArrayTable(key, v)
}
// When parsing an array table expression, each part of the key needs to be
// evaluated like a normal key, but if it returns a collection, it also needs to
// point to the last element of the collection. Unless it is the last part of
// the key, then it needs to create a new element at the end.
-func (d *decoder) handleArrayTableCollection(key ast.Iterator, v reflect.Value) (reflect.Value, error) {
+func (d *decoder) handleArrayTableCollection(key unstable.Iterator, v reflect.Value) (reflect.Value, error) {
if key.IsLast() {
return d.handleArrayTableCollectionLast(key, v)
}
@@ -390,7 +390,7 @@ func (d *decoder) handleArrayTableCollection(key ast.Iterator, v reflect.Value)
case reflect.Array:
idx := d.arrayIndex(false, v)
if idx >= v.Len() {
- return v, fmt.Errorf("toml: cannot decode array table into %s at position %d", v.Type(), idx)
+ return v, fmt.Errorf("%s at position %d", d.typeMismatchError("array table", v.Type()), idx)
}
elem := v.Index(idx)
_, err := d.handleArrayTable(key, elem)
@@ -400,7 +400,7 @@ func (d *decoder) handleArrayTableCollection(key ast.Iterator, v reflect.Value)
return d.handleArrayTable(key, v)
}
-func (d *decoder) handleKeyPart(key ast.Iterator, v reflect.Value, nextFn handlerFn, makeFn valueMakerFn) (reflect.Value, error) {
+func (d *decoder) handleKeyPart(key unstable.Iterator, v reflect.Value, nextFn handlerFn, makeFn valueMakerFn) (reflect.Value, error) {
var rv reflect.Value
// First, dispatch over v to make sure it is a valid object.
@@ -483,7 +483,7 @@ func (d *decoder) handleKeyPart(key ast.Iterator, v reflect.Value, nextFn handle
d.errorContext.Struct = t
d.errorContext.Field = path
- f := v.FieldByIndex(path)
+ f := fieldByIndex(v, path)
x, err := nextFn(key, f)
if err != nil || d.skipUntilTable {
return reflect.Value{}, err
@@ -518,7 +518,7 @@ func (d *decoder) handleKeyPart(key ast.Iterator, v reflect.Value, nextFn handle
// HandleArrayTablePart navigates the Go structure v using the key v. It is
// only used for the prefix (non-last) parts of an array-table. When
// encountering a collection, it should go to the last element.
-func (d *decoder) handleArrayTablePart(key ast.Iterator, v reflect.Value) (reflect.Value, error) {
+func (d *decoder) handleArrayTablePart(key unstable.Iterator, v reflect.Value) (reflect.Value, error) {
var makeFn valueMakerFn
if key.IsLast() {
makeFn = makeSliceInterface
@@ -530,10 +530,10 @@ func (d *decoder) handleArrayTablePart(key ast.Iterator, v reflect.Value) (refle
// HandleTable returns a reference when it has checked the next expression but
// cannot handle it.
-func (d *decoder) handleTable(key ast.Iterator, v reflect.Value) (reflect.Value, error) {
+func (d *decoder) handleTable(key unstable.Iterator, v reflect.Value) (reflect.Value, error) {
if v.Kind() == reflect.Slice {
if v.Len() == 0 {
- return reflect.Value{}, newDecodeError(key.Node().Data, "cannot store a table in a slice")
+ return reflect.Value{}, unstable.NewParserError(key.Node().Data, "cannot store a table in a slice")
}
elem := v.Index(v.Len() - 1)
x, err := d.handleTable(key, elem)
@@ -560,7 +560,7 @@ func (d *decoder) handleKeyValues(v reflect.Value) (reflect.Value, error) {
var rv reflect.Value
for d.nextExpr() {
expr := d.expr()
- if expr.Kind != ast.KeyValue {
+ if expr.Kind != unstable.KeyValue {
// Stash the expression so that fromParser can just loop and use
// the right handler.
// We could just recurse ourselves here, but at least this gives a
@@ -587,7 +587,7 @@ func (d *decoder) handleKeyValues(v reflect.Value) (reflect.Value, error) {
}
type (
- handlerFn func(key ast.Iterator, v reflect.Value) (reflect.Value, error)
+ handlerFn func(key unstable.Iterator, v reflect.Value) (reflect.Value, error)
valueMakerFn func() reflect.Value
)
@@ -599,11 +599,11 @@ func makeSliceInterface() reflect.Value {
return reflect.MakeSlice(sliceInterfaceType, 0, 16)
}
-func (d *decoder) handleTablePart(key ast.Iterator, v reflect.Value) (reflect.Value, error) {
+func (d *decoder) handleTablePart(key unstable.Iterator, v reflect.Value) (reflect.Value, error) {
return d.handleKeyPart(key, v, d.handleTable, makeMapStringInterface)
}
-func (d *decoder) tryTextUnmarshaler(node *ast.Node, v reflect.Value) (bool, error) {
+func (d *decoder) tryTextUnmarshaler(node *unstable.Node, v reflect.Value) (bool, error) {
// Special case for time, because we allow to unmarshal to it from
// different kind of AST nodes.
if v.Type() == timeType {
@@ -613,7 +613,7 @@ func (d *decoder) tryTextUnmarshaler(node *ast.Node, v reflect.Value) (bool, err
if v.CanAddr() && v.Addr().Type().Implements(textUnmarshalerType) {
err := v.Addr().Interface().(encoding.TextUnmarshaler).UnmarshalText(node.Data)
if err != nil {
- return false, newDecodeError(d.p.Raw(node.Raw), "%w", err)
+ return false, unstable.NewParserError(d.p.Raw(node.Raw), "%w", err)
}
return true, nil
@@ -622,7 +622,7 @@ func (d *decoder) tryTextUnmarshaler(node *ast.Node, v reflect.Value) (bool, err
return false, nil
}
-func (d *decoder) handleValue(value *ast.Node, v reflect.Value) error {
+func (d *decoder) handleValue(value *unstable.Node, v reflect.Value) error {
for v.Kind() == reflect.Ptr {
v = initAndDereferencePointer(v)
}
@@ -633,32 +633,32 @@ func (d *decoder) handleValue(value *ast.Node, v reflect.Value) error {
}
switch value.Kind {
- case ast.String:
+ case unstable.String:
return d.unmarshalString(value, v)
- case ast.Integer:
+ case unstable.Integer:
return d.unmarshalInteger(value, v)
- case ast.Float:
+ case unstable.Float:
return d.unmarshalFloat(value, v)
- case ast.Bool:
+ case unstable.Bool:
return d.unmarshalBool(value, v)
- case ast.DateTime:
+ case unstable.DateTime:
return d.unmarshalDateTime(value, v)
- case ast.LocalDate:
+ case unstable.LocalDate:
return d.unmarshalLocalDate(value, v)
- case ast.LocalTime:
+ case unstable.LocalTime:
return d.unmarshalLocalTime(value, v)
- case ast.LocalDateTime:
+ case unstable.LocalDateTime:
return d.unmarshalLocalDateTime(value, v)
- case ast.InlineTable:
+ case unstable.InlineTable:
return d.unmarshalInlineTable(value, v)
- case ast.Array:
+ case unstable.Array:
return d.unmarshalArray(value, v)
default:
panic(fmt.Errorf("handleValue not implemented for %s", value.Kind))
}
}
-func (d *decoder) unmarshalArray(array *ast.Node, v reflect.Value) error {
+func (d *decoder) unmarshalArray(array *unstable.Node, v reflect.Value) error {
switch v.Kind() {
case reflect.Slice:
if v.IsNil() {
@@ -729,7 +729,7 @@ func (d *decoder) unmarshalArray(array *ast.Node, v reflect.Value) error {
return nil
}
-func (d *decoder) unmarshalInlineTable(itable *ast.Node, v reflect.Value) error {
+func (d *decoder) unmarshalInlineTable(itable *unstable.Node, v reflect.Value) error {
// Make sure v is an initialized object.
switch v.Kind() {
case reflect.Map:
@@ -746,7 +746,7 @@ func (d *decoder) unmarshalInlineTable(itable *ast.Node, v reflect.Value) error
}
return d.unmarshalInlineTable(itable, elem)
default:
- return newDecodeError(itable.Data, "cannot store inline table in Go type %s", v.Kind())
+ return unstable.NewParserError(itable.Data, "cannot store inline table in Go type %s", v.Kind())
}
it := itable.Children()
@@ -765,7 +765,7 @@ func (d *decoder) unmarshalInlineTable(itable *ast.Node, v reflect.Value) error
return nil
}
-func (d *decoder) unmarshalDateTime(value *ast.Node, v reflect.Value) error {
+func (d *decoder) unmarshalDateTime(value *unstable.Node, v reflect.Value) error {
dt, err := parseDateTime(value.Data)
if err != nil {
return err
@@ -775,7 +775,7 @@ func (d *decoder) unmarshalDateTime(value *ast.Node, v reflect.Value) error {
return nil
}
-func (d *decoder) unmarshalLocalDate(value *ast.Node, v reflect.Value) error {
+func (d *decoder) unmarshalLocalDate(value *unstable.Node, v reflect.Value) error {
ld, err := parseLocalDate(value.Data)
if err != nil {
return err
@@ -792,28 +792,28 @@ func (d *decoder) unmarshalLocalDate(value *ast.Node, v reflect.Value) error {
return nil
}
-func (d *decoder) unmarshalLocalTime(value *ast.Node, v reflect.Value) error {
+func (d *decoder) unmarshalLocalTime(value *unstable.Node, v reflect.Value) error {
lt, rest, err := parseLocalTime(value.Data)
if err != nil {
return err
}
if len(rest) > 0 {
- return newDecodeError(rest, "extra characters at the end of a local time")
+ return unstable.NewParserError(rest, "extra characters at the end of a local time")
}
v.Set(reflect.ValueOf(lt))
return nil
}
-func (d *decoder) unmarshalLocalDateTime(value *ast.Node, v reflect.Value) error {
+func (d *decoder) unmarshalLocalDateTime(value *unstable.Node, v reflect.Value) error {
ldt, rest, err := parseLocalDateTime(value.Data)
if err != nil {
return err
}
if len(rest) > 0 {
- return newDecodeError(rest, "extra characters at the end of a local date time")
+ return unstable.NewParserError(rest, "extra characters at the end of a local date time")
}
if v.Type() == timeType {
@@ -828,7 +828,7 @@ func (d *decoder) unmarshalLocalDateTime(value *ast.Node, v reflect.Value) error
return nil
}
-func (d *decoder) unmarshalBool(value *ast.Node, v reflect.Value) error {
+func (d *decoder) unmarshalBool(value *unstable.Node, v reflect.Value) error {
b := value.Data[0] == 't'
switch v.Kind() {
@@ -837,13 +837,13 @@ func (d *decoder) unmarshalBool(value *ast.Node, v reflect.Value) error {
case reflect.Interface:
v.Set(reflect.ValueOf(b))
default:
- return newDecodeError(value.Data, "cannot assign boolean to a %t", b)
+ return unstable.NewParserError(value.Data, "cannot assign boolean to a %t", b)
}
return nil
}
-func (d *decoder) unmarshalFloat(value *ast.Node, v reflect.Value) error {
+func (d *decoder) unmarshalFloat(value *unstable.Node, v reflect.Value) error {
f, err := parseFloat(value.Data)
if err != nil {
return err
@@ -854,13 +854,13 @@ func (d *decoder) unmarshalFloat(value *ast.Node, v reflect.Value) error {
v.SetFloat(f)
case reflect.Float32:
if f > math.MaxFloat32 {
- return newDecodeError(value.Data, "number %f does not fit in a float32", f)
+ return unstable.NewParserError(value.Data, "number %f does not fit in a float32", f)
}
v.SetFloat(f)
case reflect.Interface:
v.Set(reflect.ValueOf(f))
default:
- return newDecodeError(value.Data, "float cannot be assigned to %s", v.Kind())
+ return unstable.NewParserError(value.Data, "float cannot be assigned to %s", v.Kind())
}
return nil
@@ -886,7 +886,7 @@ func init() {
}
}
-func (d *decoder) unmarshalInteger(value *ast.Node, v reflect.Value) error {
+func (d *decoder) unmarshalInteger(value *unstable.Node, v reflect.Value) error {
i, err := parseInteger(value.Data)
if err != nil {
return err
@@ -967,20 +967,20 @@ func (d *decoder) unmarshalInteger(value *ast.Node, v reflect.Value) error {
return nil
}
-func (d *decoder) unmarshalString(value *ast.Node, v reflect.Value) error {
+func (d *decoder) unmarshalString(value *unstable.Node, v reflect.Value) error {
switch v.Kind() {
case reflect.String:
v.SetString(string(value.Data))
case reflect.Interface:
v.Set(reflect.ValueOf(string(value.Data)))
default:
- return newDecodeError(d.p.Raw(value.Raw), "cannot store TOML string into a Go %s", v.Kind())
+ return unstable.NewParserError(d.p.Raw(value.Raw), "cannot store TOML string into a Go %s", v.Kind())
}
return nil
}
-func (d *decoder) handleKeyValue(expr *ast.Node, v reflect.Value) (reflect.Value, error) {
+func (d *decoder) handleKeyValue(expr *unstable.Node, v reflect.Value) (reflect.Value, error) {
d.strict.EnterKeyValue(expr)
v, err := d.handleKeyValueInner(expr.Key(), expr.Value(), v)
@@ -994,7 +994,7 @@ func (d *decoder) handleKeyValue(expr *ast.Node, v reflect.Value) (reflect.Value
return v, err
}
-func (d *decoder) handleKeyValueInner(key ast.Iterator, value *ast.Node, v reflect.Value) (reflect.Value, error) {
+func (d *decoder) handleKeyValueInner(key unstable.Iterator, value *unstable.Node, v reflect.Value) (reflect.Value, error) {
if key.Next() {
// Still scoping the key
return d.handleKeyValuePart(key, value, v)
@@ -1004,7 +1004,7 @@ func (d *decoder) handleKeyValueInner(key ast.Iterator, value *ast.Node, v refle
return reflect.Value{}, d.handleValue(value, v)
}
-func (d *decoder) handleKeyValuePart(key ast.Iterator, value *ast.Node, v reflect.Value) (reflect.Value, error) {
+func (d *decoder) handleKeyValuePart(key unstable.Iterator, value *unstable.Node, v reflect.Value) (reflect.Value, error) {
// contains the replacement for v
var rv reflect.Value
@@ -1071,7 +1071,7 @@ func (d *decoder) handleKeyValuePart(key ast.Iterator, value *ast.Node, v reflec
d.errorContext.Struct = t
d.errorContext.Field = path
- f := v.FieldByIndex(path)
+ f := fieldByIndex(v, path)
x, err := d.handleKeyValueInner(key, value, f)
if err != nil {
return reflect.Value{}, err
@@ -1135,6 +1135,21 @@ func initAndDereferencePointer(v reflect.Value) reflect.Value {
return elem
}
+// Same as reflect.Value.FieldByIndex, but creates pointers if needed.
+func fieldByIndex(v reflect.Value, path []int) reflect.Value {
+ for i, x := range path {
+ v = v.Field(x)
+
+ if i < len(path)-1 && v.Kind() == reflect.Ptr {
+ if v.IsNil() {
+ v.Set(reflect.New(v.Type().Elem()))
+ }
+ v = v.Elem()
+ }
+ }
+ return v
+}
+
type fieldPathsMap = map[string][]int
var globalFieldPathsCache atomic.Value // map[danger.TypeID]fieldPathsMap
@@ -1192,7 +1207,14 @@ func forEachField(t reflect.Type, path []int, do func(name string, path []int))
}
if f.Anonymous && name == "" {
- forEachField(f.Type, fieldPath, do)
+ t2 := f.Type
+ if t2.Kind() == reflect.Ptr {
+ t2 = t2.Elem()
+ }
+
+ if t2.Kind() == reflect.Struct {
+ forEachField(t2, fieldPath, do)
+ }
continue
}
diff --git a/vendor/github.com/pelletier/go-toml/v2/internal/ast/ast.go b/vendor/github.com/pelletier/go-toml/v2/unstable/ast.go
index 33c7f915..b60d9bfd 100644
--- a/vendor/github.com/pelletier/go-toml/v2/internal/ast/ast.go
+++ b/vendor/github.com/pelletier/go-toml/v2/unstable/ast.go
@@ -1,4 +1,4 @@
-package ast
+package unstable
import (
"fmt"
@@ -7,14 +7,17 @@ import (
"github.com/pelletier/go-toml/v2/internal/danger"
)
-// Iterator starts uninitialized, you need to call Next() first.
+// Iterator over a sequence of nodes.
+//
+// Starts uninitialized, you need to call Next() first.
//
// For example:
//
-// it := n.Children()
-// for it.Next() {
-// it.Node()
-// }
+// it := n.Children()
+// for it.Next() {
+// n := it.Node()
+// // do something with n
+// }
type Iterator struct {
started bool
node *Node
@@ -32,42 +35,31 @@ func (c *Iterator) Next() bool {
}
// IsLast returns true if the current node of the iterator is the last
-// one. Subsequent call to Next() will return false.
+// one. Subsequent calls to Next() will return false.
func (c *Iterator) IsLast() bool {
return c.node.next == 0
}
-// Node returns a copy of the node pointed at by the iterator.
+// Node returns a pointer to the node pointed at by the iterator.
func (c *Iterator) Node() *Node {
return c.node
}
-// Root contains a full AST.
+// Node in a TOML expression AST.
//
-// It is immutable once constructed with Builder.
-type Root struct {
- nodes []Node
-}
-
-// Iterator over the top level nodes.
-func (r *Root) Iterator() Iterator {
- it := Iterator{}
- if len(r.nodes) > 0 {
- it.node = &r.nodes[0]
- }
- return it
-}
-
-func (r *Root) at(idx Reference) *Node {
- return &r.nodes[idx]
-}
-
-// Arrays have one child per element in the array. InlineTables have
-// one child per key-value pair in the table. KeyValues have at least
-// two children. The first one is the value. The rest make a
-// potentially dotted key. Table and Array table have one child per
-// element of the key they represent (same as KeyValue, but without
-// the last node being the value).
+// Depending on Kind, its sequence of children should be interpreted
+// differently.
+//
+// - Array have one child per element in the array.
+// - InlineTable have one child per key-value in the table (each of kind
+// InlineTable).
+// - KeyValue have at least two children. The first one is the value. The rest
+// make a potentially dotted key.
+// - Table and ArrayTable's children represent a dotted key (same as
+// KeyValue, but without the first node being the value).
+//
+// When relevant, Raw describes the range of bytes this node is refering to in
+// the input document. Use Parser.Raw() to retrieve the actual bytes.
type Node struct {
Kind Kind
Raw Range // Raw bytes from the input.
@@ -80,13 +72,13 @@ type Node struct {
child int // 0 if no child
}
+// Range of bytes in the document.
type Range struct {
Offset uint32
Length uint32
}
-// Next returns a copy of the next node, or an invalid Node if there
-// is no next node.
+// Next returns a pointer to the next node, or nil if there is no next node.
func (n *Node) Next() *Node {
if n.next == 0 {
return nil
@@ -96,9 +88,9 @@ func (n *Node) Next() *Node {
return (*Node)(danger.Stride(ptr, size, n.next))
}
-// Child returns a copy of the first child node of this node. Other
-// children can be accessed calling Next on the first child. Returns
-// an invalid Node if there is none.
+// Child returns a pointer to the first child node of this node. Other children
+// can be accessed calling Next on the first child. Returns an nil if this Node
+// has no child.
func (n *Node) Child() *Node {
if n.child == 0 {
return nil
@@ -113,9 +105,9 @@ func (n *Node) Valid() bool {
return n != nil
}
-// Key returns the child nodes making the Key on a supported
-// node. Panics otherwise. They are guaranteed to be all be of the
-// Kind Key. A simple key would return just one element.
+// Key returns the children nodes making the Key on a supported node. Panics
+// otherwise. They are guaranteed to be all be of the Kind Key. A simple key
+// would return just one element.
func (n *Node) Key() Iterator {
switch n.Kind {
case KeyValue:
diff --git a/vendor/github.com/pelletier/go-toml/v2/unstable/builder.go b/vendor/github.com/pelletier/go-toml/v2/unstable/builder.go
new file mode 100644
index 00000000..9538e30d
--- /dev/null
+++ b/vendor/github.com/pelletier/go-toml/v2/unstable/builder.go
@@ -0,0 +1,71 @@
+package unstable
+
+// root contains a full AST.
+//
+// It is immutable once constructed with Builder.
+type root struct {
+ nodes []Node
+}
+
+// Iterator over the top level nodes.
+func (r *root) Iterator() Iterator {
+ it := Iterator{}
+ if len(r.nodes) > 0 {
+ it.node = &r.nodes[0]
+ }
+ return it
+}
+
+func (r *root) at(idx reference) *Node {
+ return &r.nodes[idx]
+}
+
+type reference int
+
+const invalidReference reference = -1
+
+func (r reference) Valid() bool {
+ return r != invalidReference
+}
+
+type builder struct {
+ tree root
+ lastIdx int
+}
+
+func (b *builder) Tree() *root {
+ return &b.tree
+}
+
+func (b *builder) NodeAt(ref reference) *Node {
+ return b.tree.at(ref)
+}
+
+func (b *builder) Reset() {
+ b.tree.nodes = b.tree.nodes[:0]
+ b.lastIdx = 0
+}
+
+func (b *builder) Push(n Node) reference {
+ b.lastIdx = len(b.tree.nodes)
+ b.tree.nodes = append(b.tree.nodes, n)
+ return reference(b.lastIdx)
+}
+
+func (b *builder) PushAndChain(n Node) reference {
+ newIdx := len(b.tree.nodes)
+ b.tree.nodes = append(b.tree.nodes, n)
+ if b.lastIdx >= 0 {
+ b.tree.nodes[b.lastIdx].next = newIdx - b.lastIdx
+ }
+ b.lastIdx = newIdx
+ return reference(b.lastIdx)
+}
+
+func (b *builder) AttachChild(parent reference, child reference) {
+ b.tree.nodes[parent].child = int(child) - int(parent)
+}
+
+func (b *builder) Chain(from reference, to reference) {
+ b.tree.nodes[from].next = int(to) - int(from)
+}
diff --git a/vendor/github.com/pelletier/go-toml/v2/unstable/doc.go b/vendor/github.com/pelletier/go-toml/v2/unstable/doc.go
new file mode 100644
index 00000000..7ff26c53
--- /dev/null
+++ b/vendor/github.com/pelletier/go-toml/v2/unstable/doc.go
@@ -0,0 +1,3 @@
+// Package unstable provides APIs that do not meet the backward compatibility
+// guarantees yet.
+package unstable
diff --git a/vendor/github.com/pelletier/go-toml/v2/internal/ast/kind.go b/vendor/github.com/pelletier/go-toml/v2/unstable/kind.go
index 2b50c67f..ff9df1be 100644
--- a/vendor/github.com/pelletier/go-toml/v2/internal/ast/kind.go
+++ b/vendor/github.com/pelletier/go-toml/v2/unstable/kind.go
@@ -1,25 +1,26 @@
-package ast
+package unstable
import "fmt"
+// Kind represents the type of TOML structure contained in a given Node.
type Kind int
const (
- // meta
+ // Meta
Invalid Kind = iota
Comment
Key
- // top level structures
+ // Top level structures
Table
ArrayTable
KeyValue
- // containers values
+ // Containers values
Array
InlineTable
- // values
+ // Values
String
Bool
Float
@@ -30,6 +31,7 @@ const (
DateTime
)
+// String implementation of fmt.Stringer.
func (k Kind) String() string {
switch k {
case Invalid:
diff --git a/vendor/github.com/pelletier/go-toml/v2/parser.go b/vendor/github.com/pelletier/go-toml/v2/unstable/parser.go
index 9859a795..52db88e7 100644
--- a/vendor/github.com/pelletier/go-toml/v2/parser.go
+++ b/vendor/github.com/pelletier/go-toml/v2/unstable/parser.go
@@ -1,50 +1,108 @@
-package toml
+package unstable
import (
"bytes"
+ "fmt"
"unicode"
- "github.com/pelletier/go-toml/v2/internal/ast"
+ "github.com/pelletier/go-toml/v2/internal/characters"
"github.com/pelletier/go-toml/v2/internal/danger"
)
-type parser struct {
- builder ast.Builder
- ref ast.Reference
+// ParserError describes an error relative to the content of the document.
+//
+// It cannot outlive the instance of Parser it refers to, and may cause panics
+// if the parser is reset.
+type ParserError struct {
+ Highlight []byte
+ Message string
+ Key []string // optional
+}
+
+// Error is the implementation of the error interface.
+func (e *ParserError) Error() string {
+ return e.Message
+}
+
+// NewParserError is a convenience function to create a ParserError
+//
+// Warning: Highlight needs to be a subslice of Parser.data, so only slices
+// returned by Parser.Raw are valid candidates.
+func NewParserError(highlight []byte, format string, args ...interface{}) error {
+ return &ParserError{
+ Highlight: highlight,
+ Message: fmt.Errorf(format, args...).Error(),
+ }
+}
+
+// Parser scans over a TOML-encoded document and generates an iterative AST.
+//
+// To prime the Parser, first reset it with the contents of a TOML document.
+// Then, process all top-level expressions sequentially. See Example.
+//
+// Don't forget to check Error() after you're done parsing.
+//
+// Each top-level expression needs to be fully processed before calling
+// NextExpression() again. Otherwise, calls to various Node methods may panic if
+// the parser has moved on the next expression.
+//
+// For performance reasons, go-toml doesn't make a copy of the input bytes to
+// the parser. Make sure to copy all the bytes you need to outlive the slice
+// given to the parser.
+//
+// The parser doesn't provide nodes for comments yet, nor for whitespace.
+type Parser struct {
data []byte
+ builder builder
+ ref reference
left []byte
err error
first bool
}
-func (p *parser) Range(b []byte) ast.Range {
- return ast.Range{
+// Data returns the slice provided to the last call to Reset.
+func (p *Parser) Data() []byte {
+ return p.data
+}
+
+// Range returns a range description that corresponds to a given slice of the
+// input. If the argument is not a subslice of the parser input, this function
+// panics.
+func (p *Parser) Range(b []byte) Range {
+ return Range{
Offset: uint32(danger.SubsliceOffset(p.data, b)),
Length: uint32(len(b)),
}
}
-func (p *parser) Raw(raw ast.Range) []byte {
+// Raw returns the slice corresponding to the bytes in the given range.
+func (p *Parser) Raw(raw Range) []byte {
return p.data[raw.Offset : raw.Offset+raw.Length]
}
-func (p *parser) Reset(b []byte) {
+// Reset brings the parser to its initial state for a given input. It wipes an
+// reuses internal storage to reduce allocation.
+func (p *Parser) Reset(b []byte) {
p.builder.Reset()
- p.ref = ast.InvalidReference
+ p.ref = invalidReference
p.data = b
p.left = b
p.err = nil
p.first = true
}
-//nolint:cyclop
-func (p *parser) NextExpression() bool {
+// NextExpression parses the next top-level expression. If an expression was
+// successfully parsed, it returns true. If the parser is at the end of the
+// document or an error occurred, it returns false.
+//
+// Retrieve the parsed expression with Expression().
+func (p *Parser) NextExpression() bool {
if len(p.left) == 0 || p.err != nil {
return false
}
p.builder.Reset()
- p.ref = ast.InvalidReference
+ p.ref = invalidReference
for {
if len(p.left) == 0 || p.err != nil {
@@ -73,15 +131,18 @@ func (p *parser) NextExpression() bool {
}
}
-func (p *parser) Expression() *ast.Node {
+// Expression returns a pointer to the node representing the last successfully
+// parsed expresion.
+func (p *Parser) Expression() *Node {
return p.builder.NodeAt(p.ref)
}
-func (p *parser) Error() error {
+// Error returns any error that has occured during parsing.
+func (p *Parser) Error() error {
return p.err
}
-func (p *parser) parseNewline(b []byte) ([]byte, error) {
+func (p *Parser) parseNewline(b []byte) ([]byte, error) {
if b[0] == '\n' {
return b[1:], nil
}
@@ -91,14 +152,14 @@ func (p *parser) parseNewline(b []byte) ([]byte, error) {
return rest, err
}
- return nil, newDecodeError(b[0:1], "expected newline but got %#U", b[0])
+ return nil, NewParserError(b[0:1], "expected newline but got %#U", b[0])
}
-func (p *parser) parseExpression(b []byte) (ast.Reference, []byte, error) {
+func (p *Parser) parseExpression(b []byte) (reference, []byte, error) {
// expression = ws [ comment ]
// expression =/ ws keyval ws [ comment ]
// expression =/ ws table ws [ comment ]
- ref := ast.InvalidReference
+ ref := invalidReference
b = p.parseWhitespace(b)
@@ -136,7 +197,7 @@ func (p *parser) parseExpression(b []byte) (ast.Reference, []byte, error) {
return ref, b, nil
}
-func (p *parser) parseTable(b []byte) (ast.Reference, []byte, error) {
+func (p *Parser) parseTable(b []byte) (reference, []byte, error) {
// table = std-table / array-table
if len(b) > 1 && b[1] == '[' {
return p.parseArrayTable(b)
@@ -145,12 +206,12 @@ func (p *parser) parseTable(b []byte) (ast.Reference, []byte, error) {
return p.parseStdTable(b)
}
-func (p *parser) parseArrayTable(b []byte) (ast.Reference, []byte, error) {
+func (p *Parser) parseArrayTable(b []byte) (reference, []byte, error) {
// array-table = array-table-open key array-table-close
// array-table-open = %x5B.5B ws ; [[ Double left square bracket
// array-table-close = ws %x5D.5D ; ]] Double right square bracket
- ref := p.builder.Push(ast.Node{
- Kind: ast.ArrayTable,
+ ref := p.builder.Push(Node{
+ Kind: ArrayTable,
})
b = b[2:]
@@ -174,12 +235,12 @@ func (p *parser) parseArrayTable(b []byte) (ast.Reference, []byte, error) {
return ref, b, err
}
-func (p *parser) parseStdTable(b []byte) (ast.Reference, []byte, error) {
+func (p *Parser) parseStdTable(b []byte) (reference, []byte, error) {
// std-table = std-table-open key std-table-close
// std-table-open = %x5B ws ; [ Left square bracket
// std-table-close = ws %x5D ; ] Right square bracket
- ref := p.builder.Push(ast.Node{
- Kind: ast.Table,
+ ref := p.builder.Push(Node{
+ Kind: Table,
})
b = b[1:]
@@ -199,15 +260,15 @@ func (p *parser) parseStdTable(b []byte) (ast.Reference, []byte, error) {
return ref, b, err
}
-func (p *parser) parseKeyval(b []byte) (ast.Reference, []byte, error) {
+func (p *Parser) parseKeyval(b []byte) (reference, []byte, error) {
// keyval = key keyval-sep val
- ref := p.builder.Push(ast.Node{
- Kind: ast.KeyValue,
+ ref := p.builder.Push(Node{
+ Kind: KeyValue,
})
key, b, err := p.parseKey(b)
if err != nil {
- return ast.InvalidReference, nil, err
+ return invalidReference, nil, err
}
// keyval-sep = ws %x3D ws ; =
@@ -215,12 +276,12 @@ func (p *parser) parseKeyval(b []byte) (ast.Reference, []byte, error) {
b = p.parseWhitespace(b)
if len(b) == 0 {
- return ast.InvalidReference, nil, newDecodeError(b, "expected = after a key, but the document ends there")
+ return invalidReference, nil, NewParserError(b, "expected = after a key, but the document ends there")
}
b, err = expect('=', b)
if err != nil {
- return ast.InvalidReference, nil, err
+ return invalidReference, nil, err
}
b = p.parseWhitespace(b)
@@ -237,12 +298,12 @@ func (p *parser) parseKeyval(b []byte) (ast.Reference, []byte, error) {
}
//nolint:cyclop,funlen
-func (p *parser) parseVal(b []byte) (ast.Reference, []byte, error) {
+func (p *Parser) parseVal(b []byte) (reference, []byte, error) {
// val = string / boolean / array / inline-table / date-time / float / integer
- ref := ast.InvalidReference
+ ref := invalidReference
if len(b) == 0 {
- return ref, nil, newDecodeError(b, "expected value, not eof")
+ return ref, nil, NewParserError(b, "expected value, not eof")
}
var err error
@@ -259,8 +320,8 @@ func (p *parser) parseVal(b []byte) (ast.Reference, []byte, error) {
}
if err == nil {
- ref = p.builder.Push(ast.Node{
- Kind: ast.String,
+ ref = p.builder.Push(Node{
+ Kind: String,
Raw: p.Range(raw),
Data: v,
})
@@ -277,8 +338,8 @@ func (p *parser) parseVal(b []byte) (ast.Reference, []byte, error) {
}
if err == nil {
- ref = p.builder.Push(ast.Node{
- Kind: ast.String,
+ ref = p.builder.Push(Node{
+ Kind: String,
Raw: p.Range(raw),
Data: v,
})
@@ -287,22 +348,22 @@ func (p *parser) parseVal(b []byte) (ast.Reference, []byte, error) {
return ref, b, err
case 't':
if !scanFollowsTrue(b) {
- return ref, nil, newDecodeError(atmost(b, 4), "expected 'true'")
+ return ref, nil, NewParserError(atmost(b, 4), "expected 'true'")
}
- ref = p.builder.Push(ast.Node{
- Kind: ast.Bool,
+ ref = p.builder.Push(Node{
+ Kind: Bool,
Data: b[:4],
})
return ref, b[4:], nil
case 'f':
if !scanFollowsFalse(b) {
- return ref, nil, newDecodeError(atmost(b, 5), "expected 'false'")
+ return ref, nil, NewParserError(atmost(b, 5), "expected 'false'")
}
- ref = p.builder.Push(ast.Node{
- Kind: ast.Bool,
+ ref = p.builder.Push(Node{
+ Kind: Bool,
Data: b[:5],
})
@@ -324,7 +385,7 @@ func atmost(b []byte, n int) []byte {
return b[:n]
}
-func (p *parser) parseLiteralString(b []byte) ([]byte, []byte, []byte, error) {
+func (p *Parser) parseLiteralString(b []byte) ([]byte, []byte, []byte, error) {
v, rest, err := scanLiteralString(b)
if err != nil {
return nil, nil, nil, err
@@ -333,19 +394,19 @@ func (p *parser) parseLiteralString(b []byte) ([]byte, []byte, []byte, error) {
return v, v[1 : len(v)-1], rest, nil
}
-func (p *parser) parseInlineTable(b []byte) (ast.Reference, []byte, error) {
+func (p *Parser) parseInlineTable(b []byte) (reference, []byte, error) {
// inline-table = inline-table-open [ inline-table-keyvals ] inline-table-close
// inline-table-open = %x7B ws ; {
// inline-table-close = ws %x7D ; }
// inline-table-sep = ws %x2C ws ; , Comma
// inline-table-keyvals = keyval [ inline-table-sep inline-table-keyvals ]
- parent := p.builder.Push(ast.Node{
- Kind: ast.InlineTable,
+ parent := p.builder.Push(Node{
+ Kind: InlineTable,
})
first := true
- var child ast.Reference
+ var child reference
b = b[1:]
@@ -356,7 +417,7 @@ func (p *parser) parseInlineTable(b []byte) (ast.Reference, []byte, error) {
b = p.parseWhitespace(b)
if len(b) == 0 {
- return parent, nil, newDecodeError(previousB[:1], "inline table is incomplete")
+ return parent, nil, NewParserError(previousB[:1], "inline table is incomplete")
}
if b[0] == '}' {
@@ -371,7 +432,7 @@ func (p *parser) parseInlineTable(b []byte) (ast.Reference, []byte, error) {
b = p.parseWhitespace(b)
}
- var kv ast.Reference
+ var kv reference
kv, b, err = p.parseKeyval(b)
if err != nil {
@@ -394,7 +455,7 @@ func (p *parser) parseInlineTable(b []byte) (ast.Reference, []byte, error) {
}
//nolint:funlen,cyclop
-func (p *parser) parseValArray(b []byte) (ast.Reference, []byte, error) {
+func (p *Parser) parseValArray(b []byte) (reference, []byte, error) {
// array = array-open [ array-values ] ws-comment-newline array-close
// array-open = %x5B ; [
// array-close = %x5D ; ]
@@ -405,13 +466,13 @@ func (p *parser) parseValArray(b []byte) (ast.Reference, []byte, error) {
arrayStart := b
b = b[1:]
- parent := p.builder.Push(ast.Node{
- Kind: ast.Array,
+ parent := p.builder.Push(Node{
+ Kind: Array,
})
first := true
- var lastChild ast.Reference
+ var lastChild reference
var err error
for len(b) > 0 {
@@ -421,7 +482,7 @@ func (p *parser) parseValArray(b []byte) (ast.Reference, []byte, error) {
}
if len(b) == 0 {
- return parent, nil, newDecodeError(arrayStart[:1], "array is incomplete")
+ return parent, nil, NewParserError(arrayStart[:1], "array is incomplete")
}
if b[0] == ']' {
@@ -430,7 +491,7 @@ func (p *parser) parseValArray(b []byte) (ast.Reference, []byte, error) {
if b[0] == ',' {
if first {
- return parent, nil, newDecodeError(b[0:1], "array cannot start with comma")
+ return parent, nil, NewParserError(b[0:1], "array cannot start with comma")
}
b = b[1:]
@@ -439,7 +500,7 @@ func (p *parser) parseValArray(b []byte) (ast.Reference, []byte, error) {
return parent, nil, err
}
} else if !first {
- return parent, nil, newDecodeError(b[0:1], "array elements must be separated by commas")
+ return parent, nil, NewParserError(b[0:1], "array elements must be separated by commas")
}
// TOML allows trailing commas in arrays.
@@ -447,7 +508,7 @@ func (p *parser) parseValArray(b []byte) (ast.Reference, []byte, error) {
break
}
- var valueRef ast.Reference
+ var valueRef reference
valueRef, b, err = p.parseVal(b)
if err != nil {
return parent, nil, err
@@ -472,7 +533,7 @@ func (p *parser) parseValArray(b []byte) (ast.Reference, []byte, error) {
return parent, rest, err
}
-func (p *parser) parseOptionalWhitespaceCommentNewline(b []byte) ([]byte, error) {
+func (p *Parser) parseOptionalWhitespaceCommentNewline(b []byte) ([]byte, error) {
for len(b) > 0 {
var err error
b = p.parseWhitespace(b)
@@ -501,7 +562,7 @@ func (p *parser) parseOptionalWhitespaceCommentNewline(b []byte) ([]byte, error)
return b, nil
}
-func (p *parser) parseMultilineLiteralString(b []byte) ([]byte, []byte, []byte, error) {
+func (p *Parser) parseMultilineLiteralString(b []byte) ([]byte, []byte, []byte, error) {
token, rest, err := scanMultilineLiteralString(b)
if err != nil {
return nil, nil, nil, err
@@ -520,7 +581,7 @@ func (p *parser) parseMultilineLiteralString(b []byte) ([]byte, []byte, []byte,
}
//nolint:funlen,gocognit,cyclop
-func (p *parser) parseMultilineBasicString(b []byte) ([]byte, []byte, []byte, error) {
+func (p *Parser) parseMultilineBasicString(b []byte) ([]byte, []byte, []byte, error) {
// ml-basic-string = ml-basic-string-delim [ newline ] ml-basic-body
// ml-basic-string-delim
// ml-basic-string-delim = 3quotation-mark
@@ -551,11 +612,11 @@ func (p *parser) parseMultilineBasicString(b []byte) ([]byte, []byte, []byte, er
if !escaped {
str := token[startIdx:endIdx]
- verr := utf8TomlValidAlreadyEscaped(str)
+ verr := characters.Utf8TomlValidAlreadyEscaped(str)
if verr.Zero() {
return token, str, rest, nil
}
- return nil, nil, nil, newDecodeError(str[verr.Index:verr.Index+verr.Size], "invalid UTF-8")
+ return nil, nil, nil, NewParserError(str[verr.Index:verr.Index+verr.Size], "invalid UTF-8")
}
var builder bytes.Buffer
@@ -635,13 +696,13 @@ func (p *parser) parseMultilineBasicString(b []byte) ([]byte, []byte, []byte, er
builder.WriteRune(x)
i += 8
default:
- return nil, nil, nil, newDecodeError(token[i:i+1], "invalid escaped character %#U", c)
+ return nil, nil, nil, NewParserError(token[i:i+1], "invalid escaped character %#U", c)
}
i++
} else {
- size := utf8ValidNext(token[i:])
+ size := characters.Utf8ValidNext(token[i:])
if size == 0 {
- return nil, nil, nil, newDecodeError(token[i:i+1], "invalid character %#U", c)
+ return nil, nil, nil, NewParserError(token[i:i+1], "invalid character %#U", c)
}
builder.Write(token[i : i+size])
i += size
@@ -651,7 +712,7 @@ func (p *parser) parseMultilineBasicString(b []byte) ([]byte, []byte, []byte, er
return token, builder.Bytes(), rest, nil
}
-func (p *parser) parseKey(b []byte) (ast.Reference, []byte, error) {
+func (p *Parser) parseKey(b []byte) (reference, []byte, error) {
// key = simple-key / dotted-key
// simple-key = quoted-key / unquoted-key
//
@@ -662,11 +723,11 @@ func (p *parser) parseKey(b []byte) (ast.Reference, []byte, error) {
// dot-sep = ws %x2E ws ; . Period
raw, key, b, err := p.parseSimpleKey(b)
if err != nil {
- return ast.InvalidReference, nil, err
+ return invalidReference, nil, err
}
- ref := p.builder.Push(ast.Node{
- Kind: ast.Key,
+ ref := p.builder.Push(Node{
+ Kind: Key,
Raw: p.Range(raw),
Data: key,
})
@@ -681,8 +742,8 @@ func (p *parser) parseKey(b []byte) (ast.Reference, []byte, error) {
return ref, nil, err
}
- p.builder.PushAndChain(ast.Node{
- Kind: ast.Key,
+ p.builder.PushAndChain(Node{
+ Kind: Key,
Raw: p.Range(raw),
Data: key,
})
@@ -694,9 +755,9 @@ func (p *parser) parseKey(b []byte) (ast.Reference, []byte, error) {
return ref, b, nil
}
-func (p *parser) parseSimpleKey(b []byte) (raw, key, rest []byte, err error) {
+func (p *Parser) parseSimpleKey(b []byte) (raw, key, rest []byte, err error) {
if len(b) == 0 {
- return nil, nil, nil, newDecodeError(b, "expected key but found none")
+ return nil, nil, nil, NewParserError(b, "expected key but found none")
}
// simple-key = quoted-key / unquoted-key
@@ -711,12 +772,12 @@ func (p *parser) parseSimpleKey(b []byte) (raw, key, rest []byte, err error) {
key, rest = scanUnquotedKey(b)
return key, key, rest, nil
default:
- return nil, nil, nil, newDecodeError(b[0:1], "invalid character at start of key: %c", b[0])
+ return nil, nil, nil, NewParserError(b[0:1], "invalid character at start of key: %c", b[0])
}
}
//nolint:funlen,cyclop
-func (p *parser) parseBasicString(b []byte) ([]byte, []byte, []byte, error) {
+func (p *Parser) parseBasicString(b []byte) ([]byte, []byte, []byte, error) {
// basic-string = quotation-mark *basic-char quotation-mark
// quotation-mark = %x22 ; "
// basic-char = basic-unescaped / escaped
@@ -744,11 +805,11 @@ func (p *parser) parseBasicString(b []byte) ([]byte, []byte, []byte, error) {
// validate the string and return a direct reference to the buffer.
if !escaped {
str := token[startIdx:endIdx]
- verr := utf8TomlValidAlreadyEscaped(str)
+ verr := characters.Utf8TomlValidAlreadyEscaped(str)
if verr.Zero() {
return token, str, rest, nil
}
- return nil, nil, nil, newDecodeError(str[verr.Index:verr.Index+verr.Size], "invalid UTF-8")
+ return nil, nil, nil, NewParserError(str[verr.Index:verr.Index+verr.Size], "invalid UTF-8")
}
i := startIdx
@@ -795,13 +856,13 @@ func (p *parser) parseBasicString(b []byte) ([]byte, []byte, []byte, error) {
builder.WriteRune(x)
i += 8
default:
- return nil, nil, nil, newDecodeError(token[i:i+1], "invalid escaped character %#U", c)
+ return nil, nil, nil, NewParserError(token[i:i+1], "invalid escaped character %#U", c)
}
i++
} else {
- size := utf8ValidNext(token[i:])
+ size := characters.Utf8ValidNext(token[i:])
if size == 0 {
- return nil, nil, nil, newDecodeError(token[i:i+1], "invalid character %#U", c)
+ return nil, nil, nil, NewParserError(token[i:i+1], "invalid character %#U", c)
}
builder.Write(token[i : i+size])
i += size
@@ -813,7 +874,7 @@ func (p *parser) parseBasicString(b []byte) ([]byte, []byte, []byte, error) {
func hexToRune(b []byte, length int) (rune, error) {
if len(b) < length {
- return -1, newDecodeError(b, "unicode point needs %d character, not %d", length, len(b))
+ return -1, NewParserError(b, "unicode point needs %d character, not %d", length, len(b))
}
b = b[:length]
@@ -828,19 +889,19 @@ func hexToRune(b []byte, length int) (rune, error) {
case 'A' <= c && c <= 'F':
d = uint32(c - 'A' + 10)
default:
- return -1, newDecodeError(b[i:i+1], "non-hex character")
+ return -1, NewParserError(b[i:i+1], "non-hex character")
}
r = r*16 + d
}
if r > unicode.MaxRune || 0xD800 <= r && r < 0xE000 {
- return -1, newDecodeError(b, "escape sequence is invalid Unicode code point")
+ return -1, NewParserError(b, "escape sequence is invalid Unicode code point")
}
return rune(r), nil
}
-func (p *parser) parseWhitespace(b []byte) []byte {
+func (p *Parser) parseWhitespace(b []byte) []byte {
// ws = *wschar
// wschar = %x20 ; Space
// wschar =/ %x09 ; Horizontal tab
@@ -850,24 +911,24 @@ func (p *parser) parseWhitespace(b []byte) []byte {
}
//nolint:cyclop
-func (p *parser) parseIntOrFloatOrDateTime(b []byte) (ast.Reference, []byte, error) {
+func (p *Parser) parseIntOrFloatOrDateTime(b []byte) (reference, []byte, error) {
switch b[0] {
case 'i':
if !scanFollowsInf(b) {
- return ast.InvalidReference, nil, newDecodeError(atmost(b, 3), "expected 'inf'")
+ return invalidReference, nil, NewParserError(atmost(b, 3), "expected 'inf'")
}
- return p.builder.Push(ast.Node{
- Kind: ast.Float,
+ return p.builder.Push(Node{
+ Kind: Float,
Data: b[:3],
}), b[3:], nil
case 'n':
if !scanFollowsNan(b) {
- return ast.InvalidReference, nil, newDecodeError(atmost(b, 3), "expected 'nan'")
+ return invalidReference, nil, NewParserError(atmost(b, 3), "expected 'nan'")
}
- return p.builder.Push(ast.Node{
- Kind: ast.Float,
+ return p.builder.Push(Node{
+ Kind: Float,
Data: b[:3],
}), b[3:], nil
case '+', '-':
@@ -898,7 +959,7 @@ func (p *parser) parseIntOrFloatOrDateTime(b []byte) (ast.Reference, []byte, err
return p.scanIntOrFloat(b)
}
-func (p *parser) scanDateTime(b []byte) (ast.Reference, []byte, error) {
+func (p *Parser) scanDateTime(b []byte) (reference, []byte, error) {
// scans for contiguous characters in [0-9T:Z.+-], and up to one space if
// followed by a digit.
hasDate := false
@@ -941,30 +1002,30 @@ byteLoop:
}
}
- var kind ast.Kind
+ var kind Kind
if hasTime {
if hasDate {
if hasTz {
- kind = ast.DateTime
+ kind = DateTime
} else {
- kind = ast.LocalDateTime
+ kind = LocalDateTime
}
} else {
- kind = ast.LocalTime
+ kind = LocalTime
}
} else {
- kind = ast.LocalDate
+ kind = LocalDate
}
- return p.builder.Push(ast.Node{
+ return p.builder.Push(Node{
Kind: kind,
Data: b[:i],
}), b[i:], nil
}
//nolint:funlen,gocognit,cyclop
-func (p *parser) scanIntOrFloat(b []byte) (ast.Reference, []byte, error) {
+func (p *Parser) scanIntOrFloat(b []byte) (reference, []byte, error) {
i := 0
if len(b) > 2 && b[0] == '0' && b[1] != '.' && b[1] != 'e' && b[1] != 'E' {
@@ -990,8 +1051,8 @@ func (p *parser) scanIntOrFloat(b []byte) (ast.Reference, []byte, error) {
}
}
- return p.builder.Push(ast.Node{
- Kind: ast.Integer,
+ return p.builder.Push(Node{
+ Kind: Integer,
Data: b[:i],
}), b[i:], nil
}
@@ -1013,40 +1074,40 @@ func (p *parser) scanIntOrFloat(b []byte) (ast.Reference, []byte, error) {
if c == 'i' {
if scanFollowsInf(b[i:]) {
- return p.builder.Push(ast.Node{
- Kind: ast.Float,
+ return p.builder.Push(Node{
+ Kind: Float,
Data: b[:i+3],
}), b[i+3:], nil
}
- return ast.InvalidReference, nil, newDecodeError(b[i:i+1], "unexpected character 'i' while scanning for a number")
+ return invalidReference, nil, NewParserError(b[i:i+1], "unexpected character 'i' while scanning for a number")
}
if c == 'n' {
if scanFollowsNan(b[i:]) {
- return p.builder.Push(ast.Node{
- Kind: ast.Float,
+ return p.builder.Push(Node{
+ Kind: Float,
Data: b[:i+3],
}), b[i+3:], nil
}
- return ast.InvalidReference, nil, newDecodeError(b[i:i+1], "unexpected character 'n' while scanning for a number")
+ return invalidReference, nil, NewParserError(b[i:i+1], "unexpected character 'n' while scanning for a number")
}
break
}
if i == 0 {
- return ast.InvalidReference, b, newDecodeError(b, "incomplete number")
+ return invalidReference, b, NewParserError(b, "incomplete number")
}
- kind := ast.Integer
+ kind := Integer
if isFloat {
- kind = ast.Float
+ kind = Float
}
- return p.builder.Push(ast.Node{
+ return p.builder.Push(Node{
Kind: kind,
Data: b[:i],
}), b[i:], nil
@@ -1075,11 +1136,11 @@ func isValidBinaryRune(r byte) bool {
func expect(x byte, b []byte) ([]byte, error) {
if len(b) == 0 {
- return nil, newDecodeError(b, "expected character %c but the document ended here", x)
+ return nil, NewParserError(b, "expected character %c but the document ended here", x)
}
if b[0] != x {
- return nil, newDecodeError(b[0:1], "expected character %c", x)
+ return nil, NewParserError(b[0:1], "expected character %c", x)
}
return b[1:], nil
diff --git a/vendor/github.com/pelletier/go-toml/v2/scanner.go b/vendor/github.com/pelletier/go-toml/v2/unstable/scanner.go
index bb445fab..af22ebbe 100644
--- a/vendor/github.com/pelletier/go-toml/v2/scanner.go
+++ b/vendor/github.com/pelletier/go-toml/v2/unstable/scanner.go
@@ -1,4 +1,6 @@
-package toml
+package unstable
+
+import "github.com/pelletier/go-toml/v2/internal/characters"
func scanFollows(b []byte, pattern string) bool {
n := len(pattern)
@@ -54,16 +56,16 @@ func scanLiteralString(b []byte) ([]byte, []byte, error) {
case '\'':
return b[:i+1], b[i+1:], nil
case '\n', '\r':
- return nil, nil, newDecodeError(b[i:i+1], "literal strings cannot have new lines")
+ return nil, nil, NewParserError(b[i:i+1], "literal strings cannot have new lines")
}
- size := utf8ValidNext(b[i:])
+ size := characters.Utf8ValidNext(b[i:])
if size == 0 {
- return nil, nil, newDecodeError(b[i:i+1], "invalid character")
+ return nil, nil, NewParserError(b[i:i+1], "invalid character")
}
i += size
}
- return nil, nil, newDecodeError(b[len(b):], "unterminated literal string")
+ return nil, nil, NewParserError(b[len(b):], "unterminated literal string")
}
func scanMultilineLiteralString(b []byte) ([]byte, []byte, error) {
@@ -98,39 +100,39 @@ func scanMultilineLiteralString(b []byte) ([]byte, []byte, error) {
i++
if i < len(b) && b[i] == '\'' {
- return nil, nil, newDecodeError(b[i-3:i+1], "''' not allowed in multiline literal string")
+ return nil, nil, NewParserError(b[i-3:i+1], "''' not allowed in multiline literal string")
}
return b[:i], b[i:], nil
}
case '\r':
if len(b) < i+2 {
- return nil, nil, newDecodeError(b[len(b):], `need a \n after \r`)
+ return nil, nil, NewParserError(b[len(b):], `need a \n after \r`)
}
if b[i+1] != '\n' {
- return nil, nil, newDecodeError(b[i:i+2], `need a \n after \r`)
+ return nil, nil, NewParserError(b[i:i+2], `need a \n after \r`)
}
i += 2 // skip the \n
continue
}
- size := utf8ValidNext(b[i:])
+ size := characters.Utf8ValidNext(b[i:])
if size == 0 {
- return nil, nil, newDecodeError(b[i:i+1], "invalid character")
+ return nil, nil, NewParserError(b[i:i+1], "invalid character")
}
i += size
}
- return nil, nil, newDecodeError(b[len(b):], `multiline literal string not terminated by '''`)
+ return nil, nil, NewParserError(b[len(b):], `multiline literal string not terminated by '''`)
}
func scanWindowsNewline(b []byte) ([]byte, []byte, error) {
const lenCRLF = 2
if len(b) < lenCRLF {
- return nil, nil, newDecodeError(b, "windows new line expected")
+ return nil, nil, NewParserError(b, "windows new line expected")
}
if b[1] != '\n' {
- return nil, nil, newDecodeError(b, `windows new line should be \r\n`)
+ return nil, nil, NewParserError(b, `windows new line should be \r\n`)
}
return b[:lenCRLF], b[lenCRLF:], nil
@@ -165,11 +167,11 @@ func scanComment(b []byte) ([]byte, []byte, error) {
if i+1 < len(b) && b[i+1] == '\n' {
return b[:i+1], b[i+1:], nil
}
- return nil, nil, newDecodeError(b[i:i+1], "invalid character in comment")
+ return nil, nil, NewParserError(b[i:i+1], "invalid character in comment")
}
- size := utf8ValidNext(b[i:])
+ size := characters.Utf8ValidNext(b[i:])
if size == 0 {
- return nil, nil, newDecodeError(b[i:i+1], "invalid character in comment")
+ return nil, nil, NewParserError(b[i:i+1], "invalid character in comment")
}
i += size
@@ -192,17 +194,17 @@ func scanBasicString(b []byte) ([]byte, bool, []byte, error) {
case '"':
return b[:i+1], escaped, b[i+1:], nil
case '\n', '\r':
- return nil, escaped, nil, newDecodeError(b[i:i+1], "basic strings cannot have new lines")
+ return nil, escaped, nil, NewParserError(b[i:i+1], "basic strings cannot have new lines")
case '\\':
if len(b) < i+2 {
- return nil, escaped, nil, newDecodeError(b[i:i+1], "need a character after \\")
+ return nil, escaped, nil, NewParserError(b[i:i+1], "need a character after \\")
}
escaped = true
i++ // skip the next character
}
}
- return nil, escaped, nil, newDecodeError(b[len(b):], `basic string not terminated by "`)
+ return nil, escaped, nil, NewParserError(b[len(b):], `basic string not terminated by "`)
}
func scanMultilineBasicString(b []byte) ([]byte, bool, []byte, error) {
@@ -243,27 +245,27 @@ func scanMultilineBasicString(b []byte) ([]byte, bool, []byte, error) {
i++
if i < len(b) && b[i] == '"' {
- return nil, escaped, nil, newDecodeError(b[i-3:i+1], `""" not allowed in multiline basic string`)
+ return nil, escaped, nil, NewParserError(b[i-3:i+1], `""" not allowed in multiline basic string`)
}
return b[:i], escaped, b[i:], nil
}
case '\\':
if len(b) < i+2 {
- return nil, escaped, nil, newDecodeError(b[len(b):], "need a character after \\")
+ return nil, escaped, nil, NewParserError(b[len(b):], "need a character after \\")
}
escaped = true
i++ // skip the next character
case '\r':
if len(b) < i+2 {
- return nil, escaped, nil, newDecodeError(b[len(b):], `need a \n after \r`)
+ return nil, escaped, nil, NewParserError(b[len(b):], `need a \n after \r`)
}
if b[i+1] != '\n' {
- return nil, escaped, nil, newDecodeError(b[i:i+2], `need a \n after \r`)
+ return nil, escaped, nil, NewParserError(b[i:i+2], `need a \n after \r`)
}
i++ // skip the \n
}
}
- return nil, escaped, nil, newDecodeError(b[len(b):], `multiline basic string not terminated by """`)
+ return nil, escaped, nil, NewParserError(b[len(b):], `multiline basic string not terminated by """`)
}
diff --git a/vendor/github.com/saintfish/chardet/README.md b/vendor/github.com/saintfish/chardet/README.md
index 4281eecc..41f58ee0 100644
--- a/vendor/github.com/saintfish/chardet/README.md
+++ b/vendor/github.com/saintfish/chardet/README.md
@@ -7,4 +7,4 @@ in [ICU](http://icu-project.org/)'s implementation.
## Documentation and Usage
-See [pkgdoc](http://go.pkgdoc.org/github.com/saintfish/chardet)
+See [pkgdoc](https://pkg.go.dev/github.com/saintfish/chardet)
diff --git a/vendor/github.com/slack-go/slack/auth.go b/vendor/github.com/slack-go/slack/auth.go
index f4f7f003..bf6e80d3 100644
--- a/vendor/github.com/slack-go/slack/auth.go
+++ b/vendor/github.com/slack-go/slack/auth.go
@@ -38,3 +38,37 @@ func (api *Client) SendAuthRevokeContext(ctx context.Context, token string) (*Au
return api.authRequest(ctx, "auth.revoke", values)
}
+
+type listTeamsResponse struct {
+ Teams []Team `json:"teams"`
+ SlackResponse
+}
+
+type ListTeamsParameters struct {
+ Limit int
+ Cursor string
+}
+
+// ListTeams returns all workspaces a token can access.
+// More info: https://api.slack.com/methods/admin.teams.list
+func (api *Client) ListTeams(params ListTeamsParameters) ([]Team, string, error) {
+ return api.ListTeamsContext(context.Background(), params)
+}
+
+// ListTeams returns all workspaces a token can access with a custom context.
+func (api *Client) ListTeamsContext(ctx context.Context, params ListTeamsParameters) ([]Team, string, error) {
+ values := url.Values{
+ "token": {api.token},
+ }
+ if params.Cursor != "" {
+ values.Add("cursor", params.Cursor)
+ }
+
+ response := &listTeamsResponse{}
+ err := api.postMethod(ctx, "auth.teams.list", values, response)
+ if err != nil {
+ return nil, "", err
+ }
+
+ return response.Teams, response.ResponseMetadata.Cursor, response.Err()
+}
diff --git a/vendor/github.com/slack-go/slack/block_conv.go b/vendor/github.com/slack-go/slack/block_conv.go
index 1a2c57e9..555e4811 100644
--- a/vendor/github.com/slack-go/slack/block_conv.go
+++ b/vendor/github.com/slack-go/slack/block_conv.go
@@ -112,6 +112,10 @@ func (b *InputBlock) UnmarshalJSON(data []byte) error {
e = &TimePickerBlockElement{}
case "plain_text_input":
e = &PlainTextInputBlockElement{}
+ case "email_text_input":
+ e = &EmailTextInputBlockElement{}
+ case "url_text_input":
+ e = &URLTextInputBlockElement{}
case "static_select", "external_select", "users_select", "conversations_select", "channels_select":
e = &SelectBlockElement{}
case "multi_static_select", "multi_external_select", "multi_users_select", "multi_conversations_select", "multi_channels_select":
@@ -122,6 +126,8 @@ func (b *InputBlock) UnmarshalJSON(data []byte) error {
e = &OverflowBlockElement{}
case "radio_buttons":
e = &RadioButtonsBlockElement{}
+ case "number_input":
+ e = &NumberInputBlockElement{}
default:
return errors.New("unsupported block element type")
}
@@ -186,12 +192,18 @@ func (b *BlockElements) UnmarshalJSON(data []byte) error {
blockElement = &TimePickerBlockElement{}
case "plain_text_input":
blockElement = &PlainTextInputBlockElement{}
+ case "email_text_input":
+ blockElement = &EmailTextInputBlockElement{}
+ case "url_text_input":
+ blockElement = &URLTextInputBlockElement{}
case "checkboxes":
blockElement = &CheckboxGroupsBlockElement{}
case "radio_buttons":
blockElement = &RadioButtonsBlockElement{}
case "static_select", "external_select", "users_select", "conversations_select", "channels_select":
blockElement = &SelectBlockElement{}
+ case "number_input":
+ blockElement = &NumberInputBlockElement{}
default:
return fmt.Errorf("unsupported block element type %v", blockElementType)
}
diff --git a/vendor/github.com/slack-go/slack/block_element.go b/vendor/github.com/slack-go/slack/block_element.go
index 643529ff..aba29c6b 100644
--- a/vendor/github.com/slack-go/slack/block_element.go
+++ b/vendor/github.com/slack-go/slack/block_element.go
@@ -11,6 +11,9 @@ const (
METTimepicker MessageElementType = "timepicker"
METPlainTextInput MessageElementType = "plain_text_input"
METRadioButtons MessageElementType = "radio_buttons"
+ METEmailTextInput MessageElementType = "email_text_input"
+ METURLTextInput MessageElementType = "url_text_input"
+ METNumber MessageElementType = "number_input"
MixedElementImage MixedElementType = "mixed_image"
MixedElementText MixedElementType = "mixed_text"
@@ -389,6 +392,64 @@ func NewTimePickerBlockElement(actionID string) *TimePickerBlockElement {
}
}
+// EmailTextInputBlockElement creates a field where a user can enter email
+// data.
+// email-text-input elements are currently only available in modals.
+//
+// More Information: https://api.slack.com/reference/block-kit/block-elements#email
+type EmailTextInputBlockElement struct {
+ Type MessageElementType `json:"type"`
+ ActionID string `json:"action_id,omitempty"`
+ Placeholder *TextBlockObject `json:"placeholder,omitempty"`
+ InitialValue string `json:"initial_value,omitempty"`
+ DispatchActionConfig *DispatchActionConfig `json:"dispatch_action_config,omitempty"`
+ FocusOnLoad bool `json:"focus_on_load,omitempty"`
+}
+
+// ElementType returns the type of the Element
+func (s EmailTextInputBlockElement) ElementType() MessageElementType {
+ return s.Type
+}
+
+// NewEmailTextInputBlockElement returns an instance of a plain-text input
+// element
+func NewEmailTextInputBlockElement(placeholder *TextBlockObject, actionID string) *EmailTextInputBlockElement {
+ return &EmailTextInputBlockElement{
+ Type: METEmailTextInput,
+ ActionID: actionID,
+ Placeholder: placeholder,
+ }
+}
+
+// URLTextInputBlockElement creates a field where a user can enter url data.
+//
+// url-text-input elements are currently only available in modals.
+//
+// More Information: https://api.slack.com/reference/block-kit/block-elements#url
+type URLTextInputBlockElement struct {
+ Type MessageElementType `json:"type"`
+ ActionID string `json:"action_id,omitempty"`
+ Placeholder *TextBlockObject `json:"placeholder,omitempty"`
+ InitialValue string `json:"initial_value,omitempty"`
+ DispatchActionConfig *DispatchActionConfig `json:"dispatch_action_config,omitempty"`
+ FocusOnLoad bool `json:"focus_on_load,omitempty"`
+}
+
+// ElementType returns the type of the Element
+func (s URLTextInputBlockElement) ElementType() MessageElementType {
+ return s.Type
+}
+
+// NewURLTextInputBlockElement returns an instance of a plain-text input
+// element
+func NewURLTextInputBlockElement(placeholder *TextBlockObject, actionID string) *URLTextInputBlockElement {
+ return &URLTextInputBlockElement{
+ Type: METURLTextInput,
+ ActionID: actionID,
+ Placeholder: placeholder,
+ }
+}
+
// PlainTextInputBlockElement creates a field where a user can enter freeform
// data.
// Plain-text input elements are currently only available in modals.
@@ -475,3 +536,34 @@ func NewRadioButtonsBlockElement(actionID string, options ...*OptionBlockObject)
Options: options,
}
}
+
+// NumberInputBlockElement creates a field where a user can enter number
+// data.
+// Number input elements are currently only available in modals.
+//
+// More Information: https://api.slack.com/reference/block-kit/block-elements#number
+type NumberInputBlockElement struct {
+ Type MessageElementType `json:"type"`
+ IsDecimalAllowed bool `json:"is_decimal_allowed"`
+ ActionID string `json:"action_id,omitempty"`
+ Placeholder *TextBlockObject `json:"placeholder,omitempty"`
+ InitialValue string `json:"initial_value,omitempty"`
+ MinValue string `json:"min_value,omitempty"`
+ MaxValue string `json:"max_value,omitempty"`
+ DispatchActionConfig *DispatchActionConfig `json:"dispatch_action_config,omitempty"`
+}
+
+// ElementType returns the type of the Element
+func (s NumberInputBlockElement) ElementType() MessageElementType {
+ return s.Type
+}
+
+// NewNumberInputBlockElement returns an instance of a number input element
+func NewNumberInputBlockElement(placeholder *TextBlockObject, actionID string, isDecimalAllowed bool) *NumberInputBlockElement {
+ return &NumberInputBlockElement{
+ Type: METNumber,
+ ActionID: actionID,
+ Placeholder: placeholder,
+ IsDecimalAllowed: isDecimalAllowed,
+ }
+}
diff --git a/vendor/github.com/slack-go/slack/block_rich_text.go b/vendor/github.com/slack-go/slack/block_rich_text.go
index 281db213..555a6198 100644
--- a/vendor/github.com/slack-go/slack/block_rich_text.go
+++ b/vendor/github.com/slack-go/slack/block_rich_text.go
@@ -327,17 +327,17 @@ func NewRichTextSectionUserGroupElement(usergroupID string) *RichTextSectionUser
type RichTextSectionDateElement struct {
Type RichTextSectionElementType `json:"type"`
- Timestamp string `json:"timestamp"`
+ Timestamp JSONTime `json:"timestamp"`
}
func (r RichTextSectionDateElement) RichTextSectionElementType() RichTextSectionElementType {
return r.Type
}
-func NewRichTextSectionDateElement(timestamp string) *RichTextSectionDateElement {
+func NewRichTextSectionDateElement(timestamp int64) *RichTextSectionDateElement {
return &RichTextSectionDateElement{
Type: RTSEDate,
- Timestamp: timestamp,
+ Timestamp: JSONTime(timestamp),
}
}
diff --git a/vendor/github.com/slack-go/slack/conversation.go b/vendor/github.com/slack-go/slack/conversation.go
index e523716c..44f06ea9 100644
--- a/vendor/github.com/slack-go/slack/conversation.go
+++ b/vendor/github.com/slack-go/slack/conversation.go
@@ -2,6 +2,7 @@ package slack
import (
"context"
+ "errors"
"net/url"
"strconv"
"strings"
@@ -71,6 +72,7 @@ type GetConversationsForUserParameters struct {
Types []string
Limit int
ExcludeArchived bool
+ TeamID string
}
type responseMetaData struct {
@@ -137,6 +139,10 @@ func (api *Client) GetConversationsForUserContext(ctx context.Context, params *G
if params.ExcludeArchived {
values.Add("exclude_archived", "true")
}
+ if params.TeamID != "" {
+ values.Add("team_id", params.TeamID)
+ }
+
response := struct {
Channels []Channel `json:"channels"`
ResponseMetaData responseMetaData `json:"response_metadata"`
@@ -337,17 +343,26 @@ func (api *Client) CloseConversationContext(ctx context.Context, channelID strin
return response.NoOp, response.AlreadyClosed, response.Err()
}
+type CreateConversationParams struct {
+ ChannelName string
+ IsPrivate bool
+ TeamID string
+}
+
// CreateConversation initiates a public or private channel-based conversation
-func (api *Client) CreateConversation(channelName string, isPrivate bool) (*Channel, error) {
- return api.CreateConversationContext(context.Background(), channelName, isPrivate)
+func (api *Client) CreateConversation(params CreateConversationParams) (*Channel, error) {
+ return api.CreateConversationContext(context.Background(), params)
}
// CreateConversationContext initiates a public or private channel-based conversation with a custom context
-func (api *Client) CreateConversationContext(ctx context.Context, channelName string, isPrivate bool) (*Channel, error) {
+func (api *Client) CreateConversationContext(ctx context.Context, params CreateConversationParams) (*Channel, error) {
values := url.Values{
"token": {api.token},
- "name": {channelName},
- "is_private": {strconv.FormatBool(isPrivate)},
+ "name": {params.ChannelName},
+ "is_private": {strconv.FormatBool(params.IsPrivate)},
+ }
+ if params.TeamID != "" {
+ values.Set("team_id", params.TeamID)
}
response, err := api.channelRequest(ctx, "conversations.create", values)
if err != nil {
@@ -357,17 +372,33 @@ func (api *Client) CreateConversationContext(ctx context.Context, channelName st
return &response.Channel, nil
}
+// GetConversationInfoInput Defines the parameters of a GetConversationInfo and GetConversationInfoContext function
+type GetConversationInfoInput struct {
+ ChannelID string
+ IncludeLocale bool
+ IncludeNumMembers bool
+}
+
// GetConversationInfo retrieves information about a conversation
-func (api *Client) GetConversationInfo(channelID string, includeLocale bool) (*Channel, error) {
- return api.GetConversationInfoContext(context.Background(), channelID, includeLocale)
+func (api *Client) GetConversationInfo(input *GetConversationInfoInput) (*Channel, error) {
+ return api.GetConversationInfoContext(context.Background(), input)
}
// GetConversationInfoContext retrieves information about a conversation with a custom context
-func (api *Client) GetConversationInfoContext(ctx context.Context, channelID string, includeLocale bool) (*Channel, error) {
+func (api *Client) GetConversationInfoContext(ctx context.Context, input *GetConversationInfoInput) (*Channel, error) {
+ if input == nil {
+ return nil, errors.New("GetConversationInfoInput must not be nil")
+ }
+
+ if input.ChannelID == "" {
+ return nil, errors.New("ChannelID must be defined")
+ }
+
values := url.Values{
- "token": {api.token},
- "channel": {channelID},
- "include_locale": {strconv.FormatBool(includeLocale)},
+ "token": {api.token},
+ "channel": {input.ChannelID},
+ "include_locale": {strconv.FormatBool(input.IncludeLocale)},
+ "include_num_members": {strconv.FormatBool(input.IncludeNumMembers)},
}
response, err := api.channelRequest(ctx, "conversations.info", values)
if err != nil {
@@ -398,13 +429,14 @@ func (api *Client) LeaveConversationContext(ctx context.Context, channelID strin
}
type GetConversationRepliesParameters struct {
- ChannelID string
- Timestamp string
- Cursor string
- Inclusive bool
- Latest string
- Limit int
- Oldest string
+ ChannelID string
+ Timestamp string
+ Cursor string
+ Inclusive bool
+ Latest string
+ Limit int
+ Oldest string
+ IncludeAllMetadata bool
}
// GetConversationReplies retrieves a thread of messages posted to a conversation
@@ -436,6 +468,11 @@ func (api *Client) GetConversationRepliesContext(ctx context.Context, params *Ge
} else {
values.Add("inclusive", "0")
}
+ if params.IncludeAllMetadata {
+ values.Add("include_all_metadata", "1")
+ } else {
+ values.Add("include_all_metadata", "0")
+ }
response := struct {
SlackResponse
HasMore bool `json:"has_more"`
diff --git a/vendor/github.com/slack-go/slack/files.go b/vendor/github.com/slack-go/slack/files.go
index e7cfe1fe..35628442 100644
--- a/vendor/github.com/slack-go/slack/files.go
+++ b/vendor/github.com/slack-go/slack/files.go
@@ -2,6 +2,7 @@ package slack
import (
"context"
+ "encoding/json"
"fmt"
"io"
"net/url"
@@ -145,6 +146,58 @@ type ListFilesParameters struct {
Cursor string
}
+type UploadFileV2Parameters struct {
+ File string
+ FileSize int
+ Content string
+ Reader io.Reader
+ Filename string
+ Title string
+ InitialComment string
+ Channel string
+ ThreadTimestamp string
+ AltTxt string
+ SnippetText string
+}
+
+type getUploadURLExternalParameters struct {
+ altText string
+ fileSize int
+ fileName string
+ snippetText string
+}
+
+type getUploadURLExternalResponse struct {
+ UploadURL string `json:"upload_url"`
+ FileID string `json:"file_id"`
+ SlackResponse
+}
+
+type uploadToURLParameters struct {
+ UploadURL string
+ Reader io.Reader
+ File string
+ Content string
+ Filename string
+}
+
+type FileSummary struct {
+ ID string `json:"id"`
+ Title string `json:"title"`
+}
+
+type completeUploadExternalParameters struct {
+ title string
+ channel string
+ initialComment string
+ threadTimestamp string
+}
+
+type completeUploadExternalResponse struct {
+ SlackResponse
+ Files []FileSummary `json:"files"`
+}
+
type fileResponseFull struct {
File `json:"file"`
Paging `json:"paging"`
@@ -416,3 +469,129 @@ func (api *Client) ShareFilePublicURLContext(ctx context.Context, fileID string)
}
return &response.File, response.Comments, &response.Paging, nil
}
+
+// getUploadURLExternal gets a URL and fileID from slack which can later be used to upload a file
+func (api *Client) getUploadURLExternal(ctx context.Context, params getUploadURLExternalParameters) (*getUploadURLExternalResponse, error) {
+ values := url.Values{
+ "token": {api.token},
+ "filename": {params.fileName},
+ "length": {strconv.Itoa(params.fileSize)},
+ }
+ if params.altText != "" {
+ values.Add("initial_comment", params.altText)
+ }
+ if params.snippetText != "" {
+ values.Add("thread_ts", params.snippetText)
+ }
+ response := &getUploadURLExternalResponse{}
+ err := api.postMethod(ctx, "files.getUploadURLExternal", values, response)
+ if err != nil {
+ return nil, err
+ }
+
+ return response, response.Err()
+}
+
+// uploadToURL uploads the file to the provided URL using post method
+func (api *Client) uploadToURL(ctx context.Context, params uploadToURLParameters) (err error) {
+ values := url.Values{}
+ if params.Content != "" {
+ values.Add("content", params.Content)
+ values.Add("token", api.token)
+ err = postForm(ctx, api.httpclient, params.UploadURL, values, nil, api)
+ } else if params.File != "" {
+ err = postLocalWithMultipartResponse(ctx, api.httpclient, params.UploadURL, params.File, "file", api.token, values, nil, api)
+ } else if params.Reader != nil {
+ err = postWithMultipartResponse(ctx, api.httpclient, params.UploadURL, params.Filename, "file", api.token, values, params.Reader, nil, api)
+ }
+ return err
+}
+
+// completeUploadExternal once files are uploaded, this completes the upload and shares it to the specified channel
+func (api *Client) completeUploadExternal(ctx context.Context, fileID string, params completeUploadExternalParameters) (file *completeUploadExternalResponse, err error) {
+ request := []FileSummary{{ID: fileID, Title: params.title}}
+ requestBytes, err := json.Marshal(request)
+ if err != nil {
+ return nil, err
+ }
+ values := url.Values{
+ "token": {api.token},
+ "files": {string(requestBytes)},
+ "channel_id": {params.channel},
+ }
+
+ if params.initialComment != "" {
+ values.Add("initial_comment", params.initialComment)
+ }
+ if params.threadTimestamp != "" {
+ values.Add("thread_ts", params.threadTimestamp)
+ }
+ response := &completeUploadExternalResponse{}
+ err = api.postMethod(ctx, "files.completeUploadExternal", values, response)
+ if err != nil {
+ return nil, err
+ }
+ if response.Err() != nil {
+ return nil, response.Err()
+ }
+ return response, nil
+}
+
+// UploadFileV2 uploads file to a given slack channel using 3 steps -
+// 1. Get an upload URL using files.getUploadURLExternal API
+// 2. Send the file as a post to the URL provided by slack
+// 3. Complete the upload and share it to the specified channel using files.completeUploadExternal
+func (api *Client) UploadFileV2(params UploadFileV2Parameters) (*FileSummary, error) {
+ return api.UploadFileV2Context(context.Background(), params)
+}
+
+// UploadFileV2 uploads file to a given slack channel using 3 steps with a custom context -
+// 1. Get an upload URL using files.getUploadURLExternal API
+// 2. Send the file as a post to the URL provided by slack
+// 3. Complete the upload and share it to the specified channel using files.completeUploadExternal
+func (api *Client) UploadFileV2Context(ctx context.Context, params UploadFileV2Parameters) (file *FileSummary, err error) {
+ if params.Filename == "" {
+ return nil, fmt.Errorf("file.upload.v2: filename cannot be empty")
+ }
+ if params.FileSize == 0 {
+ return nil, fmt.Errorf("file.upload.v2: file size cannot be 0")
+ }
+ if params.Channel == "" {
+ return nil, fmt.Errorf("file.upload.v2: channel cannot be empty")
+ }
+ u, err := api.getUploadURLExternal(ctx, getUploadURLExternalParameters{
+ altText: params.AltTxt,
+ fileName: params.Filename,
+ fileSize: params.FileSize,
+ snippetText: params.SnippetText,
+ })
+ if err != nil {
+ return nil, err
+ }
+
+ err = api.uploadToURL(ctx, uploadToURLParameters{
+ UploadURL: u.UploadURL,
+ Reader: params.Reader,
+ File: params.File,
+ Content: params.Content,
+ Filename: params.Filename,
+ })
+ if err != nil {
+ return nil, err
+ }
+
+ c, err := api.completeUploadExternal(ctx, u.FileID, completeUploadExternalParameters{
+ title: params.Title,
+ channel: params.Channel,
+ initialComment: params.InitialComment,
+ threadTimestamp: params.ThreadTimestamp,
+ })
+ if err != nil {
+ return nil, err
+ }
+ if len(c.Files) != 1 {
+ return nil, fmt.Errorf("file.upload.v2: something went wrong; received %d files instead of 1", len(c.Files))
+ }
+
+ return &c.Files[0], nil
+}
diff --git a/vendor/github.com/slack-go/slack/misc.go b/vendor/github.com/slack-go/slack/misc.go
index 9180116a..7e5a8d54 100644
--- a/vendor/github.com/slack-go/slack/misc.go
+++ b/vendor/github.com/slack-go/slack/misc.go
@@ -307,6 +307,9 @@ type responseParser func(*http.Response) error
func newJSONParser(dst interface{}) responseParser {
return func(resp *http.Response) error {
+ if dst == nil {
+ return nil
+ }
return json.NewDecoder(resp.Body).Decode(dst)
}
}
diff --git a/vendor/github.com/slack-go/slack/team.go b/vendor/github.com/slack-go/slack/team.go
index 029e2b5b..d21a1b64 100644
--- a/vendor/github.com/slack-go/slack/team.go
+++ b/vendor/github.com/slack-go/slack/team.go
@@ -24,6 +24,26 @@ type TeamInfo struct {
Icon map[string]interface{} `json:"icon"`
}
+type TeamProfileResponse struct {
+ Profile TeamProfile `json:"profile"`
+ SlackResponse
+}
+
+type TeamProfile struct {
+ Fields []TeamProfileField `json:"fields"`
+}
+
+type TeamProfileField struct {
+ ID string `json:"id"`
+ Ordering int `json:"ordering"`
+ Label string `json:"label"`
+ Hint string `json:"hint"`
+ Type string `json:"type"`
+ PossibleValues []string `json:"possible_values"`
+ IsHidden bool `json:"is_hidden"`
+ Options map[string]bool `json:"options"`
+}
+
type LoginResponse struct {
Logins []Login `json:"logins"`
Paging `json:"paging"`
@@ -95,11 +115,41 @@ func (api *Client) accessLogsRequest(ctx context.Context, path string, values ur
return response, response.Err()
}
+func (api *Client) teamProfileRequest(ctx context.Context, client httpClient, path string, values url.Values) (*TeamProfileResponse, error) {
+ response := &TeamProfileResponse{}
+ err := api.postMethod(ctx, path, values, response)
+ if err != nil {
+ return nil, err
+ }
+ return response, response.Err()
+}
+
// GetTeamInfo gets the Team Information of the user
func (api *Client) GetTeamInfo() (*TeamInfo, error) {
return api.GetTeamInfoContext(context.Background())
}
+// GetOtherTeamInfoContext gets Team information for any team with a custom context
+func (api *Client) GetOtherTeamInfoContext(ctx context.Context, team string) (*TeamInfo, error) {
+ if team == "" {
+ return api.GetTeamInfoContext(ctx)
+ }
+ values := url.Values{
+ "token": {api.token},
+ }
+ values.Add("team", team)
+ response, err := api.teamRequest(ctx, "team.info", values)
+ if err != nil {
+ return nil, err
+ }
+ return &response.Team, nil
+}
+
+// GetOtherTeamInfo gets Team information for any team
+func (api *Client) GetOtherTeamInfo(team string) (*TeamInfo, error) {
+ return api.GetOtherTeamInfoContext(context.Background(), team)
+}
+
// GetTeamInfoContext gets the Team Information of the user with a custom context
func (api *Client) GetTeamInfoContext(ctx context.Context) (*TeamInfo, error) {
values := url.Values{
@@ -113,6 +163,25 @@ func (api *Client) GetTeamInfoContext(ctx context.Context) (*TeamInfo, error) {
return &response.Team, nil
}
+// GetTeamProfile gets the Team Profile settings of the user
+func (api *Client) GetTeamProfile() (*TeamProfile, error) {
+ return api.GetTeamProfileContext(context.Background())
+}
+
+// GetTeamProfileContext gets the Team Profile settings of the user with a custom context
+func (api *Client) GetTeamProfileContext(ctx context.Context) (*TeamProfile, error) {
+ values := url.Values{
+ "token": {api.token},
+ }
+
+ response, err := api.teamProfileRequest(ctx, api.httpclient, "team.profile.get", values)
+ if err != nil {
+ return nil, err
+ }
+ return &response.Profile, nil
+
+}
+
// GetAccessLogs retrieves a page of logins according to the parameters given
func (api *Client) GetAccessLogs(params AccessLogParameters) ([]Login, *Paging, error) {
return api.GetAccessLogsContext(context.Background(), params)
diff --git a/vendor/github.com/slack-go/slack/users.go b/vendor/github.com/slack-go/slack/users.go
index d22b44f8..55f42118 100644
--- a/vendor/github.com/slack-go/slack/users.go
+++ b/vendor/github.com/slack-go/slack/users.go
@@ -17,30 +17,38 @@ const (
// UserProfile contains all the information details of a given user
type UserProfile struct {
- FirstName string `json:"first_name"`
- LastName string `json:"last_name"`
- RealName string `json:"real_name"`
- RealNameNormalized string `json:"real_name_normalized"`
- DisplayName string `json:"display_name"`
- DisplayNameNormalized string `json:"display_name_normalized"`
- Email string `json:"email"`
- Skype string `json:"skype"`
- Phone string `json:"phone"`
- Image24 string `json:"image_24"`
- Image32 string `json:"image_32"`
- Image48 string `json:"image_48"`
- Image72 string `json:"image_72"`
- Image192 string `json:"image_192"`
- Image512 string `json:"image_512"`
- ImageOriginal string `json:"image_original"`
- Title string `json:"title"`
- BotID string `json:"bot_id,omitempty"`
- ApiAppID string `json:"api_app_id,omitempty"`
- StatusText string `json:"status_text,omitempty"`
- StatusEmoji string `json:"status_emoji,omitempty"`
- StatusExpiration int `json:"status_expiration"`
- Team string `json:"team"`
- Fields UserProfileCustomFields `json:"fields"`
+ FirstName string `json:"first_name"`
+ LastName string `json:"last_name"`
+ RealName string `json:"real_name"`
+ RealNameNormalized string `json:"real_name_normalized"`
+ DisplayName string `json:"display_name"`
+ DisplayNameNormalized string `json:"display_name_normalized"`
+ Email string `json:"email"`
+ Skype string `json:"skype"`
+ Phone string `json:"phone"`
+ Image24 string `json:"image_24"`
+ Image32 string `json:"image_32"`
+ Image48 string `json:"image_48"`
+ Image72 string `json:"image_72"`
+ Image192 string `json:"image_192"`
+ Image512 string `json:"image_512"`
+ ImageOriginal string `json:"image_original"`
+ Title string `json:"title"`
+ BotID string `json:"bot_id,omitempty"`
+ ApiAppID string `json:"api_app_id,omitempty"`
+ StatusText string `json:"status_text,omitempty"`
+ StatusEmoji string `json:"status_emoji,omitempty"`
+ StatusEmojiDisplayInfo []UserProfileStatusEmojiDisplayInfo `json:"status_emoji_display_info,omitempty"`
+ StatusExpiration int `json:"status_expiration"`
+ Team string `json:"team"`
+ Fields UserProfileCustomFields `json:"fields"`
+}
+
+type UserProfileStatusEmojiDisplayInfo struct {
+ EmojiName string `json:"emoji_name"`
+ DisplayAlias string `json:"display_alias,omitempty"`
+ DisplayURL string `json:"display_url,omitempty"`
+ Unicode string `json:"unicode,omitempty"`
}
// UserProfileCustomFields represents user profile's custom fields.
@@ -556,6 +564,55 @@ func (api *Client) SetUserRealNameContextWithUser(ctx context.Context, user, rea
return response.Err()
}
+// SetUserCustomFields sets Custom Profile fields on the provided users account. Due to the non-repeating elements
+// within the request, a map fields is required. The key in the map signifies the field that will be updated.
+//
+// Note: You may need to change the way the custom field is populated within the Profile section of the Admin Console from
+// SCIM or User Entered to API.
+//
+// See GetTeamProfile for information to retrieve possible fields for your account.
+func (api *Client) SetUserCustomFields(userID string, customFields map[string]UserProfileCustomField) error {
+ return api.SetUserCustomFieldsContext(context.Background(), userID, customFields)
+}
+
+// SetUserCustomFieldsContext will set a users custom profile field with context.
+//
+// For more information see SetUserCustomFields
+func (api *Client) SetUserCustomFieldsContext(ctx context.Context, userID string, customFields map[string]UserProfileCustomField) error {
+
+ // Convert data to data type with custom marshall / unmarshall
+ // For more information, see UserProfileCustomFields definition.
+ updateFields := UserProfileCustomFields{}
+ updateFields.SetMap(customFields)
+
+ // This anonymous struct is needed to set the fields level of the request data. The base struct for
+ // UserProfileCustomFields has an unexported variable named fields that does not contain a struct tag,
+ // which has resulted in this configuration.
+ profile, err := json.Marshal(&struct {
+ Fields UserProfileCustomFields `json:"fields"`
+ }{
+ Fields: updateFields,
+ })
+
+ if err != nil {
+ return err
+ }
+
+ values := url.Values{
+ "token": {api.token},
+ "user": {userID},
+ "profile": {string(profile)},
+ }
+
+ response := &userResponseFull{}
+ if err := postForm(ctx, api.httpclient, APIURL+"users.profile.set", values, response, api); err != nil {
+ return err
+ }
+
+ return response.Err()
+
+}
+
// SetUserCustomStatus will set a custom status and emoji for the currently
// authenticated user. If statusEmoji is "" and statusText is not, the Slack API
// will automatically set it to ":speech_balloon:". Otherwise, if both are ""
diff --git a/vendor/github.com/slack-go/slack/webhooks.go b/vendor/github.com/slack-go/slack/webhooks.go
index 2f8fb47f..e3233536 100644
--- a/vendor/github.com/slack-go/slack/webhooks.go
+++ b/vendor/github.com/slack-go/slack/webhooks.go
@@ -21,8 +21,8 @@ type WebhookMessage struct {
Parse string `json:"parse,omitempty"`
Blocks *Blocks `json:"blocks,omitempty"`
ResponseType string `json:"response_type,omitempty"`
- ReplaceOriginal bool `json:"replace_original,omitempty"`
- DeleteOriginal bool `json:"delete_original,omitempty"`
+ ReplaceOriginal bool `json:"replace_original"`
+ DeleteOriginal bool `json:"delete_original"`
ReplyBroadcast bool `json:"reply_broadcast,omitempty"`
}
diff --git a/vendor/github.com/slack-go/slack/websocket_reactions.go b/vendor/github.com/slack-go/slack/websocket_reactions.go
index e4973878..6098a6ca 100644
--- a/vendor/github.com/slack-go/slack/websocket_reactions.go
+++ b/vendor/github.com/slack-go/slack/websocket_reactions.go
@@ -1,7 +1,7 @@
package slack
-// reactionItem is a lighter-weight item than is returned by the reactions list.
-type reactionItem struct {
+// ReactionItem is a lighter-weight item than is returned by the reactions list.
+type ReactionItem struct {
Type string `json:"type"`
Channel string `json:"channel,omitempty"`
File string `json:"file,omitempty"`
@@ -9,17 +9,17 @@ type reactionItem struct {
Timestamp string `json:"ts,omitempty"`
}
-type reactionEvent struct {
+type ReactionEvent struct {
Type string `json:"type"`
User string `json:"user"`
ItemUser string `json:"item_user"`
- Item reactionItem `json:"item"`
+ Item ReactionItem `json:"item"`
Reaction string `json:"reaction"`
EventTimestamp string `json:"event_ts"`
}
// ReactionAddedEvent represents the Reaction added event
-type ReactionAddedEvent reactionEvent
+type ReactionAddedEvent ReactionEvent
// ReactionRemovedEvent represents the Reaction removed event
-type ReactionRemovedEvent reactionEvent
+type ReactionRemovedEvent ReactionEvent
diff --git a/vendor/github.com/slack-go/slack/workflow_step_execute.go b/vendor/github.com/slack-go/slack/workflow_step_execute.go
index 18516f23..32db9ba0 100644
--- a/vendor/github.com/slack-go/slack/workflow_step_execute.go
+++ b/vendor/github.com/slack-go/slack/workflow_step_execute.go
@@ -19,10 +19,10 @@ type (
}
)
-type WorkflowStepCompletedRequestOption func(opt WorkflowStepCompletedRequest) error
+type WorkflowStepCompletedRequestOption func(opt *WorkflowStepCompletedRequest) error
func WorkflowStepCompletedRequestOptionOutput(outputs map[string]string) WorkflowStepCompletedRequestOption {
- return func(opt WorkflowStepCompletedRequest) error {
+ return func(opt *WorkflowStepCompletedRequest) error {
if len(outputs) > 0 {
opt.Outputs = outputs
}
@@ -33,7 +33,7 @@ func WorkflowStepCompletedRequestOptionOutput(outputs map[string]string) Workflo
// WorkflowStepCompleted indicates step is completed
func (api *Client) WorkflowStepCompleted(workflowStepExecuteID string, options ...WorkflowStepCompletedRequestOption) error {
// More information: https://api.slack.com/methods/workflows.stepCompleted
- r := WorkflowStepCompletedRequest{
+ r := &WorkflowStepCompletedRequest{
WorkflowStepExecuteID: workflowStepExecuteID,
}
for _, option := range options {
diff --git a/vendor/github.com/spf13/afero/.travis.yml b/vendor/github.com/spf13/afero/.travis.yml
deleted file mode 100644
index e944f594..00000000
--- a/vendor/github.com/spf13/afero/.travis.yml
+++ /dev/null
@@ -1,26 +0,0 @@
-sudo: false
-language: go
-arch:
- - amd64
- - ppc64e
-
-go:
- - "1.14"
- - "1.15"
- - "1.16"
- - tip
-
-os:
- - linux
- - osx
-
-matrix:
- allow_failures:
- - go: tip
- fast_finish: true
-
-script:
- - go build -v ./...
- - go test -count=1 -cover -race -v ./...
- - go vet ./...
- - FILES=$(gofmt -s -l . zipfs sftpfs mem tarfs); if [[ -n "${FILES}" ]]; then echo "You have go format errors; gofmt your changes"; exit 1; fi
diff --git a/vendor/github.com/spf13/afero/README.md b/vendor/github.com/spf13/afero/README.md
index cab257f5..3bafbfdf 100644
--- a/vendor/github.com/spf13/afero/README.md
+++ b/vendor/github.com/spf13/afero/README.md
@@ -2,7 +2,7 @@
A FileSystem Abstraction System for Go
-[![Build Status](https://travis-ci.org/spf13/afero.svg)](https://travis-ci.org/spf13/afero) [![Build status](https://ci.appveyor.com/api/projects/status/github/spf13/afero?branch=master&svg=true)](https://ci.appveyor.com/project/spf13/afero) [![GoDoc](https://godoc.org/github.com/spf13/afero?status.svg)](https://godoc.org/github.com/spf13/afero) [![Join the chat at https://gitter.im/spf13/afero](https://badges.gitter.im/Dev%20Chat.svg)](https://gitter.im/spf13/afero?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
+[![Test](https://github.com/spf13/afero/actions/workflows/test.yml/badge.svg)](https://github.com/spf13/afero/actions/workflows/test.yml) [![GoDoc](https://godoc.org/github.com/spf13/afero?status.svg)](https://godoc.org/github.com/spf13/afero) [![Join the chat at https://gitter.im/spf13/afero](https://badges.gitter.im/Dev%20Chat.svg)](https://gitter.im/spf13/afero?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
# Overview
diff --git a/vendor/github.com/spf13/afero/afero.go b/vendor/github.com/spf13/afero/afero.go
index 469ff7d2..199480cd 100644
--- a/vendor/github.com/spf13/afero/afero.go
+++ b/vendor/github.com/spf13/afero/afero.go
@@ -103,8 +103,8 @@ type Fs interface {
var (
ErrFileClosed = errors.New("File is closed")
- ErrOutOfRange = errors.New("Out of range")
- ErrTooLarge = errors.New("Too large")
+ ErrOutOfRange = errors.New("out of range")
+ ErrTooLarge = errors.New("too large")
ErrFileNotFound = os.ErrNotExist
ErrFileExists = os.ErrExist
ErrDestinationExists = os.ErrExist
diff --git a/vendor/github.com/spf13/afero/appveyor.yml b/vendor/github.com/spf13/afero/appveyor.yml
index 5d2f34bf..65e20e8c 100644
--- a/vendor/github.com/spf13/afero/appveyor.yml
+++ b/vendor/github.com/spf13/afero/appveyor.yml
@@ -1,3 +1,5 @@
+# This currently does nothing. We have moved to GitHub action, but this is kept
+# until spf13 has disabled this project in AppVeyor.
version: '{build}'
clone_folder: C:\gopath\src\github.com\spf13\afero
environment:
@@ -6,10 +8,3 @@ build_script:
- cmd: >-
go version
- go env
-
- go get -v github.com/spf13/afero/...
-
- go build -v github.com/spf13/afero/...
-test_script:
-- cmd: go test -count=1 -cover -race -v github.com/spf13/afero/...
diff --git a/vendor/github.com/spf13/afero/basepath.go b/vendor/github.com/spf13/afero/basepath.go
index 4f983282..70a1d916 100644
--- a/vendor/github.com/spf13/afero/basepath.go
+++ b/vendor/github.com/spf13/afero/basepath.go
@@ -1,6 +1,7 @@
package afero
import (
+ "io/fs"
"os"
"path/filepath"
"runtime"
@@ -8,7 +9,10 @@ import (
"time"
)
-var _ Lstater = (*BasePathFs)(nil)
+var (
+ _ Lstater = (*BasePathFs)(nil)
+ _ fs.ReadDirFile = (*BasePathFile)(nil)
+)
// The BasePathFs restricts all operations to a given path within an Fs.
// The given file name to the operations on this Fs will be prepended with
@@ -33,6 +37,14 @@ func (f *BasePathFile) Name() string {
return strings.TrimPrefix(sourcename, filepath.Clean(f.path))
}
+func (f *BasePathFile) ReadDir(n int) ([]fs.DirEntry, error) {
+ if rdf, ok := f.File.(fs.ReadDirFile); ok {
+ return rdf.ReadDir(n)
+
+ }
+ return readDirFile{f.File}.ReadDir(n)
+}
+
func NewBasePathFs(source Fs, path string) Fs {
return &BasePathFs{source: source, path: path}
}
diff --git a/vendor/github.com/spf13/afero/const_bsds.go b/vendor/github.com/spf13/afero/const_bsds.go
index 18b45824..eed0f225 100644
--- a/vendor/github.com/spf13/afero/const_bsds.go
+++ b/vendor/github.com/spf13/afero/const_bsds.go
@@ -11,6 +11,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+//go:build aix || darwin || openbsd || freebsd || netbsd || dragonfly
// +build aix darwin openbsd freebsd netbsd dragonfly
package afero
diff --git a/vendor/github.com/spf13/afero/const_win_unix.go b/vendor/github.com/spf13/afero/const_win_unix.go
index 2b850e4d..004d57e2 100644
--- a/vendor/github.com/spf13/afero/const_win_unix.go
+++ b/vendor/github.com/spf13/afero/const_win_unix.go
@@ -10,12 +10,8 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
-// +build !darwin
-// +build !openbsd
-// +build !freebsd
-// +build !dragonfly
-// +build !netbsd
-// +build !aix
+//go:build !darwin && !openbsd && !freebsd && !dragonfly && !netbsd && !aix
+// +build !darwin,!openbsd,!freebsd,!dragonfly,!netbsd,!aix
package afero
diff --git a/vendor/github.com/spf13/afero/httpFs.go b/vendor/github.com/spf13/afero/httpFs.go
index 2b86e30d..ac0de6d5 100644
--- a/vendor/github.com/spf13/afero/httpFs.go
+++ b/vendor/github.com/spf13/afero/httpFs.go
@@ -29,7 +29,7 @@ type httpDir struct {
}
func (d httpDir) Open(name string) (http.File, error) {
- if filepath.Separator != '/' && strings.IndexRune(name, filepath.Separator) >= 0 ||
+ if filepath.Separator != '/' && strings.ContainsRune(name, filepath.Separator) ||
strings.Contains(name, "\x00") {
return nil, errors.New("http: invalid character in file path")
}
diff --git a/vendor/github.com/spf13/afero/internal/common/adapters.go b/vendor/github.com/spf13/afero/internal/common/adapters.go
new file mode 100644
index 00000000..60685caa
--- /dev/null
+++ b/vendor/github.com/spf13/afero/internal/common/adapters.go
@@ -0,0 +1,27 @@
+// Copyright © 2022 Steve Francia <spf@spf13.com>.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package common
+
+import "io/fs"
+
+// FileInfoDirEntry provides an adapter from os.FileInfo to fs.DirEntry
+type FileInfoDirEntry struct {
+ fs.FileInfo
+}
+
+var _ fs.DirEntry = FileInfoDirEntry{}
+
+func (d FileInfoDirEntry) Type() fs.FileMode { return d.FileInfo.Mode().Type() }
+
+func (d FileInfoDirEntry) Info() (fs.FileInfo, error) { return d.FileInfo, nil }
diff --git a/vendor/github.com/spf13/afero/iofs.go b/vendor/github.com/spf13/afero/iofs.go
index c8034553..938b9316 100644
--- a/vendor/github.com/spf13/afero/iofs.go
+++ b/vendor/github.com/spf13/afero/iofs.go
@@ -1,3 +1,4 @@
+//go:build go1.16
// +build go1.16
package afero
@@ -7,7 +8,10 @@ import (
"io/fs"
"os"
"path"
+ "sort"
"time"
+
+ "github.com/spf13/afero/internal/common"
)
// IOFS adopts afero.Fs to stdlib io/fs.FS
@@ -66,14 +70,31 @@ func (iofs IOFS) Glob(pattern string) ([]string, error) {
}
func (iofs IOFS) ReadDir(name string) ([]fs.DirEntry, error) {
- items, err := ReadDir(iofs.Fs, name)
+ f, err := iofs.Fs.Open(name)
if err != nil {
return nil, iofs.wrapError("readdir", name, err)
}
+ defer f.Close()
+
+ if rdf, ok := f.(fs.ReadDirFile); ok {
+ items, err := rdf.ReadDir(-1)
+ if err != nil {
+ return nil, iofs.wrapError("readdir", name, err)
+ }
+ sort.Slice(items, func(i, j int) bool { return items[i].Name() < items[j].Name() })
+ return items, nil
+ }
+
+ items, err := f.Readdir(-1)
+ if err != nil {
+ return nil, iofs.wrapError("readdir", name, err)
+ }
+ sort.Sort(byName(items))
+
ret := make([]fs.DirEntry, len(items))
for i := range items {
- ret[i] = dirEntry{items[i]}
+ ret[i] = common.FileInfoDirEntry{FileInfo: items[i]}
}
return ret, nil
@@ -108,17 +129,6 @@ func (IOFS) wrapError(op, path string, err error) error {
}
}
-// dirEntry provides adapter from os.FileInfo to fs.DirEntry
-type dirEntry struct {
- fs.FileInfo
-}
-
-var _ fs.DirEntry = dirEntry{}
-
-func (d dirEntry) Type() fs.FileMode { return d.FileInfo.Mode().Type() }
-
-func (d dirEntry) Info() (fs.FileInfo, error) { return d.FileInfo, nil }
-
// readDirFile provides adapter from afero.File to fs.ReadDirFile needed for correct Open
type readDirFile struct {
File
@@ -134,7 +144,7 @@ func (r readDirFile) ReadDir(n int) ([]fs.DirEntry, error) {
ret := make([]fs.DirEntry, len(items))
for i := range items {
- ret[i] = dirEntry{items[i]}
+ ret[i] = common.FileInfoDirEntry{FileInfo: items[i]}
}
return ret, nil
diff --git a/vendor/github.com/spf13/afero/ioutil.go b/vendor/github.com/spf13/afero/ioutil.go
index a403133e..386c9cdc 100644
--- a/vendor/github.com/spf13/afero/ioutil.go
+++ b/vendor/github.com/spf13/afero/ioutil.go
@@ -141,7 +141,7 @@ func WriteFile(fs Fs, filename string, data []byte, perm os.FileMode) error {
// We generate random temporary file names so that there's a good
// chance the file doesn't exist yet - keeps the number of tries in
// TempFile to a minimum.
-var rand uint32
+var randNum uint32
var randmu sync.Mutex
func reseed() uint32 {
@@ -150,12 +150,12 @@ func reseed() uint32 {
func nextRandom() string {
randmu.Lock()
- r := rand
+ r := randNum
if r == 0 {
r = reseed()
}
r = r*1664525 + 1013904223 // constants from Numerical Recipes
- rand = r
+ randNum = r
randmu.Unlock()
return strconv.Itoa(int(1e9 + r%1e9))[1:]
}
@@ -194,7 +194,7 @@ func TempFile(fs Fs, dir, pattern string) (f File, err error) {
if os.IsExist(err) {
if nconflict++; nconflict > 10 {
randmu.Lock()
- rand = reseed()
+ randNum = reseed()
randmu.Unlock()
}
continue
@@ -226,7 +226,7 @@ func TempDir(fs Fs, dir, prefix string) (name string, err error) {
if os.IsExist(err) {
if nconflict++; nconflict > 10 {
randmu.Lock()
- rand = reseed()
+ randNum = reseed()
randmu.Unlock()
}
continue
diff --git a/vendor/github.com/spf13/afero/mem/file.go b/vendor/github.com/spf13/afero/mem/file.go
index 5ef8b6a3..3cf4693b 100644
--- a/vendor/github.com/spf13/afero/mem/file.go
+++ b/vendor/github.com/spf13/afero/mem/file.go
@@ -18,15 +18,20 @@ import (
"bytes"
"errors"
"io"
+ "io/fs"
"os"
"path/filepath"
"sync"
"sync/atomic"
"time"
+
+ "github.com/spf13/afero/internal/common"
)
const FilePathSeparator = string(filepath.Separator)
+var _ fs.ReadDirFile = &File{}
+
type File struct {
// atomic requires 64-bit alignment for struct field access
at int64
@@ -183,10 +188,23 @@ func (f *File) Readdirnames(n int) (names []string, err error) {
return names, err
}
+// Implements fs.ReadDirFile
+func (f *File) ReadDir(n int) ([]fs.DirEntry, error) {
+ fi, err := f.Readdir(n)
+ if err != nil {
+ return nil, err
+ }
+ di := make([]fs.DirEntry, len(fi))
+ for i, f := range fi {
+ di[i] = common.FileInfoDirEntry{FileInfo: f}
+ }
+ return di, nil
+}
+
func (f *File) Read(b []byte) (n int, err error) {
f.fileData.Lock()
defer f.fileData.Unlock()
- if f.closed == true {
+ if f.closed {
return 0, ErrFileClosed
}
if len(b) > 0 && int(f.at) == len(f.fileData.data) {
@@ -214,7 +232,7 @@ func (f *File) ReadAt(b []byte, off int64) (n int, err error) {
}
func (f *File) Truncate(size int64) error {
- if f.closed == true {
+ if f.closed {
return ErrFileClosed
}
if f.readOnly {
@@ -236,7 +254,7 @@ func (f *File) Truncate(size int64) error {
}
func (f *File) Seek(offset int64, whence int) (int64, error) {
- if f.closed == true {
+ if f.closed {
return 0, ErrFileClosed
}
switch whence {
@@ -251,7 +269,7 @@ func (f *File) Seek(offset int64, whence int) (int64, error) {
}
func (f *File) Write(b []byte) (n int, err error) {
- if f.closed == true {
+ if f.closed {
return 0, ErrFileClosed
}
if f.readOnly {
@@ -330,8 +348,8 @@ func (s *FileInfo) Size() int64 {
var (
ErrFileClosed = errors.New("File is closed")
- ErrOutOfRange = errors.New("Out of range")
- ErrTooLarge = errors.New("Too large")
+ ErrOutOfRange = errors.New("out of range")
+ ErrTooLarge = errors.New("too large")
ErrFileNotFound = os.ErrNotExist
ErrFileExists = os.ErrExist
ErrDestinationExists = os.ErrExist
diff --git a/vendor/github.com/spf13/afero/memmap.go b/vendor/github.com/spf13/afero/memmap.go
index ea0798d8..d06975e7 100644
--- a/vendor/github.com/spf13/afero/memmap.go
+++ b/vendor/github.com/spf13/afero/memmap.go
@@ -142,6 +142,11 @@ func (m *MemMapFs) Mkdir(name string, perm os.FileMode) error {
}
m.mu.Lock()
+ // Dobule check that it doesn't exist.
+ if _, ok := m.getData()[name]; ok {
+ m.mu.Unlock()
+ return &os.PathError{Op: "mkdir", Path: name, Err: ErrFileExists}
+ }
item := mem.CreateDir(name)
mem.SetMode(item, os.ModeDir|perm)
m.getData()[name] = item
diff --git a/vendor/github.com/spf13/afero/unionFile.go b/vendor/github.com/spf13/afero/unionFile.go
index 34f99a40..333d367f 100644
--- a/vendor/github.com/spf13/afero/unionFile.go
+++ b/vendor/github.com/spf13/afero/unionFile.go
@@ -65,7 +65,7 @@ func (f *UnionFile) ReadAt(s []byte, o int64) (int, error) {
if f.Layer != nil {
n, err := f.Layer.ReadAt(s, o)
if (err == nil || err == io.EOF) && f.Base != nil {
- _, err = f.Base.Seek(o+int64(n), os.SEEK_SET)
+ _, err = f.Base.Seek(o+int64(n), io.SeekStart)
}
return n, err
}
diff --git a/vendor/github.com/spf13/afero/util.go b/vendor/github.com/spf13/afero/util.go
index 4f253f48..cb7de23f 100644
--- a/vendor/github.com/spf13/afero/util.go
+++ b/vendor/github.com/spf13/afero/util.go
@@ -25,6 +25,7 @@ import (
"strings"
"unicode"
+ "golang.org/x/text/runes"
"golang.org/x/text/transform"
"golang.org/x/text/unicode/norm"
)
@@ -158,16 +159,12 @@ func UnicodeSanitize(s string) string {
// Transform characters with accents into plain forms.
func NeuterAccents(s string) string {
- t := transform.Chain(norm.NFD, transform.RemoveFunc(isMn), norm.NFC)
+ t := transform.Chain(norm.NFD, runes.Remove(runes.In(unicode.Mn)), norm.NFC)
result, _, _ := transform.String(t, string(s))
return result
}
-func isMn(r rune) bool {
- return unicode.Is(unicode.Mn, r) // Mn: nonspacing marks
-}
-
func (a Afero) FileContainsBytes(filename string, subslice []byte) (bool, error) {
return FileContainsBytes(a.Fs, filename, subslice)
}
@@ -299,6 +296,9 @@ func IsEmpty(fs Fs, path string) (bool, error) {
}
defer f.Close()
list, err := f.Readdir(-1)
+ if err != nil {
+ return false, err
+ }
return len(list) == 0, nil
}
return fi.Size() == 0, nil
diff --git a/vendor/github.com/spf13/viper/Makefile b/vendor/github.com/spf13/viper/Makefile
index 02d3e371..3f4234d3 100644
--- a/vendor/github.com/spf13/viper/Makefile
+++ b/vendor/github.com/spf13/viper/Makefile
@@ -16,7 +16,7 @@ endif
# Dependency versions
GOTESTSUM_VERSION = 1.8.0
-GOLANGCI_VERSION = 1.45.2
+GOLANGCI_VERSION = 1.50.1
# Add the ability to override some variables
# Use with care
@@ -48,7 +48,7 @@ bin/golangci-lint: bin/golangci-lint-${GOLANGCI_VERSION}
@ln -sf golangci-lint-${GOLANGCI_VERSION} bin/golangci-lint
bin/golangci-lint-${GOLANGCI_VERSION}:
@mkdir -p bin
- curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | bash -s -- -b ./bin/ v${GOLANGCI_VERSION}
+ curl -sfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | bash -s -- -b ./bin/ v${GOLANGCI_VERSION}
@mv bin/golangci-lint "$@"
.PHONY: lint
diff --git a/vendor/github.com/spf13/viper/README.md b/vendor/github.com/spf13/viper/README.md
index c14e8927..cd392905 100644
--- a/vendor/github.com/spf13/viper/README.md
+++ b/vendor/github.com/spf13/viper/README.md
@@ -8,10 +8,10 @@
[![Mentioned in Awesome Go](https://awesome.re/mentioned-badge-flat.svg)](https://github.com/avelino/awesome-go#configuration)
[![run on repl.it](https://repl.it/badge/github/sagikazarmark/Viper-example)](https://repl.it/@sagikazarmark/Viper-example#main.go)
-[![GitHub Workflow Status](https://img.shields.io/github/workflow/status/spf13/viper/CI?style=flat-square)](https://github.com/spf13/viper/actions?query=workflow%3ACI)
+[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/spf13/viper/ci.yaml?branch=master&style=flat-square)](https://github.com/spf13/viper/actions?query=workflow%3ACI)
[![Join the chat at https://gitter.im/spf13/viper](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/spf13/viper?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![Go Report Card](https://goreportcard.com/badge/github.com/spf13/viper?style=flat-square)](https://goreportcard.com/report/github.com/spf13/viper)
-![Go Version](https://img.shields.io/badge/go%20version-%3E=1.15-61CFDD.svg?style=flat-square)
+![Go Version](https://img.shields.io/badge/go%20version-%3E=1.16-61CFDD.svg?style=flat-square)
[![PkgGoDev](https://pkg.go.dev/badge/mod/github.com/spf13/viper)](https://pkg.go.dev/mod/github.com/spf13/viper)
**Go configuration with fangs!**
@@ -40,8 +40,8 @@ go get github.com/spf13/viper
## What is Viper?
-Viper is a complete configuration solution for Go applications including 12-Factor apps. It is designed
-to work within an application, and can handle all types of configuration needs
+Viper is a complete configuration solution for Go applications including [12-Factor apps](https://12factor.net/#the_twelve_factors).
+It is designed to work within an application, and can handle all types of configuration needs
and formats. It supports:
* setting defaults
@@ -119,7 +119,7 @@ viper.AddConfigPath("$HOME/.appname") // call multiple times to add many search
viper.AddConfigPath(".") // optionally look for config in the working directory
err := viper.ReadInConfig() // Find and read the config file
if err != nil { // Handle errors reading the config file
- panic(fmt.Errorf("Fatal error config file: %w \n", err))
+ panic(fmt.Errorf("fatal error config file: %w", err))
}
```
@@ -447,6 +447,13 @@ viper.SetConfigType("json") // because there is no file extension in a stream of
err := viper.ReadRemoteConfig()
```
+#### etcd3
+```go
+viper.AddRemoteProvider("etcd3", "http://127.0.0.1:4001","/config/hugo.json")
+viper.SetConfigType("json") // because there is no file extension in a stream of bytes, supported extensions are "json", "toml", "yaml", "yml", "properties", "props", "prop", "env", "dotenv"
+err := viper.ReadRemoteConfig()
+```
+
#### Consul
You need to set a key to Consul key/value storage with JSON value containing your desired config.
For example, create a Consul key/value store key `MY_CONSUL_KEY` with value:
@@ -594,7 +601,7 @@ configuration level.
Viper can access array indices by using numbers in the path. For example:
-```json
+```jsonc
{
"host": {
"address": "localhost",
@@ -622,7 +629,7 @@ GetInt("host.ports.1") // returns 6029
Lastly, if there exists a key that matches the delimited key path, its value
will be returned instead. E.g.
-```json
+```jsonc
{
"datastore.metric.host": "0.0.0.0",
"host": {
diff --git a/vendor/github.com/spf13/viper/internal/encoding/toml/codec.go b/vendor/github.com/spf13/viper/internal/encoding/toml/codec.go
index 45fddc8b..a993c599 100644
--- a/vendor/github.com/spf13/viper/internal/encoding/toml/codec.go
+++ b/vendor/github.com/spf13/viper/internal/encoding/toml/codec.go
@@ -1,39 +1,16 @@
-//go:build viper_toml1
-// +build viper_toml1
-
package toml
import (
- "github.com/pelletier/go-toml"
+ "github.com/pelletier/go-toml/v2"
)
// Codec implements the encoding.Encoder and encoding.Decoder interfaces for TOML encoding.
type Codec struct{}
func (Codec) Encode(v map[string]interface{}) ([]byte, error) {
- t, err := toml.TreeFromMap(v)
- if err != nil {
- return nil, err
- }
-
- s, err := t.ToTomlString()
- if err != nil {
- return nil, err
- }
-
- return []byte(s), nil
+ return toml.Marshal(v)
}
func (Codec) Decode(b []byte, v map[string]interface{}) error {
- tree, err := toml.LoadBytes(b)
- if err != nil {
- return err
- }
-
- tmap := tree.ToMap()
- for key, value := range tmap {
- v[key] = value
- }
-
- return nil
+ return toml.Unmarshal(b, &v)
}
diff --git a/vendor/github.com/spf13/viper/internal/encoding/toml/codec2.go b/vendor/github.com/spf13/viper/internal/encoding/toml/codec2.go
deleted file mode 100644
index 112c6d37..00000000
--- a/vendor/github.com/spf13/viper/internal/encoding/toml/codec2.go
+++ /dev/null
@@ -1,19 +0,0 @@
-//go:build !viper_toml1
-// +build !viper_toml1
-
-package toml
-
-import (
- "github.com/pelletier/go-toml/v2"
-)
-
-// Codec implements the encoding.Encoder and encoding.Decoder interfaces for TOML encoding.
-type Codec struct{}
-
-func (Codec) Encode(v map[string]interface{}) ([]byte, error) {
- return toml.Marshal(v)
-}
-
-func (Codec) Decode(b []byte, v map[string]interface{}) error {
- return toml.Unmarshal(b, &v)
-}
diff --git a/vendor/github.com/spf13/viper/internal/encoding/yaml/codec.go b/vendor/github.com/spf13/viper/internal/encoding/yaml/codec.go
index 24cc19df..82dc136a 100644
--- a/vendor/github.com/spf13/viper/internal/encoding/yaml/codec.go
+++ b/vendor/github.com/spf13/viper/internal/encoding/yaml/codec.go
@@ -1,6 +1,6 @@
package yaml
-// import "gopkg.in/yaml.v2"
+import "gopkg.in/yaml.v3"
// Codec implements the encoding.Encoder and encoding.Decoder interfaces for YAML encoding.
type Codec struct{}
diff --git a/vendor/github.com/spf13/viper/internal/encoding/yaml/yaml2.go b/vendor/github.com/spf13/viper/internal/encoding/yaml/yaml2.go
deleted file mode 100644
index 4c398c2f..00000000
--- a/vendor/github.com/spf13/viper/internal/encoding/yaml/yaml2.go
+++ /dev/null
@@ -1,14 +0,0 @@
-//go:build viper_yaml2
-// +build viper_yaml2
-
-package yaml
-
-import yamlv2 "gopkg.in/yaml.v2"
-
-var yaml = struct {
- Marshal func(in interface{}) (out []byte, err error)
- Unmarshal func(in []byte, out interface{}) (err error)
-}{
- Marshal: yamlv2.Marshal,
- Unmarshal: yamlv2.Unmarshal,
-}
diff --git a/vendor/github.com/spf13/viper/internal/encoding/yaml/yaml3.go b/vendor/github.com/spf13/viper/internal/encoding/yaml/yaml3.go
deleted file mode 100644
index 3a4775ce..00000000
--- a/vendor/github.com/spf13/viper/internal/encoding/yaml/yaml3.go
+++ /dev/null
@@ -1,14 +0,0 @@
-//go:build !viper_yaml2
-// +build !viper_yaml2
-
-package yaml
-
-import yamlv3 "gopkg.in/yaml.v3"
-
-var yaml = struct {
- Marshal func(in interface{}) (out []byte, err error)
- Unmarshal func(in []byte, out interface{}) (err error)
-}{
- Marshal: yamlv3.Marshal,
- Unmarshal: yamlv3.Unmarshal,
-}
diff --git a/vendor/github.com/spf13/viper/logger.go b/vendor/github.com/spf13/viper/logger.go
index 0115067a..a64e1446 100644
--- a/vendor/github.com/spf13/viper/logger.go
+++ b/vendor/github.com/spf13/viper/logger.go
@@ -7,8 +7,8 @@ import (
)
// Logger is a unified interface for various logging use cases and practices, including:
-// - leveled logging
-// - structured logging
+// - leveled logging
+// - structured logging
type Logger interface {
// Trace logs a Trace event.
//
diff --git a/vendor/github.com/spf13/viper/util.go b/vendor/github.com/spf13/viper/util.go
index ee7a86d9..64e65750 100644
--- a/vendor/github.com/spf13/viper/util.go
+++ b/vendor/github.com/spf13/viper/util.go
@@ -64,18 +64,25 @@ func copyAndInsensitiviseMap(m map[string]interface{}) map[string]interface{} {
return nm
}
+func insensitiviseVal(val interface{}) interface{} {
+ switch val.(type) {
+ case map[interface{}]interface{}:
+ // nested map: cast and recursively insensitivise
+ val = cast.ToStringMap(val)
+ insensitiviseMap(val.(map[string]interface{}))
+ case map[string]interface{}:
+ // nested map: recursively insensitivise
+ insensitiviseMap(val.(map[string]interface{}))
+ case []interface{}:
+ // nested array: recursively insensitivise
+ insensitiveArray(val.([]interface{}))
+ }
+ return val
+}
+
func insensitiviseMap(m map[string]interface{}) {
for key, val := range m {
- switch val.(type) {
- case map[interface{}]interface{}:
- // nested map: cast and recursively insensitivise
- val = cast.ToStringMap(val)
- insensitiviseMap(val.(map[string]interface{}))
- case map[string]interface{}:
- // nested map: recursively insensitivise
- insensitiviseMap(val.(map[string]interface{}))
- }
-
+ val = insensitiviseVal(val)
lower := strings.ToLower(key)
if key != lower {
// remove old key (not lower-cased)
@@ -86,6 +93,12 @@ func insensitiviseMap(m map[string]interface{}) {
}
}
+func insensitiveArray(a []interface{}) {
+ for i, val := range a {
+ a[i] = insensitiviseVal(val)
+ }
+}
+
func absPathify(logger Logger, inPath string) string {
logger.Info("trying to resolve absolute path", "path", inPath)
diff --git a/vendor/github.com/spf13/viper/viper.go b/vendor/github.com/spf13/viper/viper.go
index a3812e92..06610fc5 100644
--- a/vendor/github.com/spf13/viper/viper.go
+++ b/vendor/github.com/spf13/viper/viper.go
@@ -132,10 +132,10 @@ type DecoderConfigOption func(*mapstructure.DecoderConfig)
// DecodeHook returns a DecoderConfigOption which overrides the default
// DecoderConfig.DecodeHook value, the default is:
//
-// mapstructure.ComposeDecodeHookFunc(
-// mapstructure.StringToTimeDurationHookFunc(),
-// mapstructure.StringToSliceHookFunc(","),
-// )
+// mapstructure.ComposeDecodeHookFunc(
+// mapstructure.StringToTimeDurationHookFunc(),
+// mapstructure.StringToSliceHookFunc(","),
+// )
func DecodeHook(hook mapstructure.DecodeHookFunc) DecoderConfigOption {
return func(c *mapstructure.DecoderConfig) {
c.DecodeHook = hook
@@ -156,18 +156,18 @@ func DecodeHook(hook mapstructure.DecodeHookFunc) DecoderConfigOption {
//
// For example, if values from the following sources were loaded:
//
-// Defaults : {
-// "secret": "",
-// "user": "default",
-// "endpoint": "https://localhost"
-// }
-// Config : {
-// "user": "root"
-// "secret": "defaultsecret"
-// }
-// Env : {
-// "secret": "somesecretkey"
-// }
+// Defaults : {
+// "secret": "",
+// "user": "default",
+// "endpoint": "https://localhost"
+// }
+// Config : {
+// "user": "root"
+// "secret": "defaultsecret"
+// }
+// Env : {
+// "secret": "somesecretkey"
+// }
//
// The resulting config will have the following values:
//
@@ -300,7 +300,7 @@ func NewWithOptions(opts ...Option) *Viper {
func Reset() {
v = New()
SupportedExts = []string{"json", "toml", "yaml", "yml", "properties", "props", "prop", "hcl", "tfvars", "dotenv", "env", "ini"}
- SupportedRemoteProviders = []string{"etcd", "consul", "firestore"}
+ SupportedRemoteProviders = []string{"etcd", "etcd3", "consul", "firestore"}
}
// TODO: make this lazy initialization instead
@@ -419,15 +419,20 @@ type RemoteProvider interface {
var SupportedExts = []string{"json", "toml", "yaml", "yml", "properties", "props", "prop", "hcl", "tfvars", "dotenv", "env", "ini"}
// SupportedRemoteProviders are universally supported remote providers.
-var SupportedRemoteProviders = []string{"etcd", "consul", "firestore"}
+var SupportedRemoteProviders = []string{"etcd", "etcd3", "consul", "firestore"}
+// OnConfigChange sets the event handler that is called when a config file changes.
func OnConfigChange(run func(in fsnotify.Event)) { v.OnConfigChange(run) }
+
+// OnConfigChange sets the event handler that is called when a config file changes.
func (v *Viper) OnConfigChange(run func(in fsnotify.Event)) {
v.onConfigChange = run
}
+// WatchConfig starts watching a config file for changes.
func WatchConfig() { v.WatchConfig() }
+// WatchConfig starts watching a config file for changes.
func (v *Viper) WatchConfig() {
initWG := sync.WaitGroup{}
initWG.Add(1)
@@ -463,9 +468,8 @@ func (v *Viper) WatchConfig() {
// we only care about the config file with the following cases:
// 1 - if the config file was modified or created
// 2 - if the real path to the config file changed (eg: k8s ConfigMap replacement)
- const writeOrCreateMask = fsnotify.Write | fsnotify.Create
if (filepath.Clean(event.Name) == configFile &&
- event.Op&writeOrCreateMask != 0) ||
+ (event.Has(fsnotify.Write) || event.Has(fsnotify.Create))) ||
(currentConfigFile != "" && currentConfigFile != realConfigFile) {
realConfigFile = currentConfigFile
err := v.ReadInConfig()
@@ -475,8 +479,7 @@ func (v *Viper) WatchConfig() {
if v.onConfigChange != nil {
v.onConfigChange(event)
}
- } else if filepath.Clean(event.Name) == configFile &&
- event.Op&fsnotify.Remove != 0 {
+ } else if filepath.Clean(event.Name) == configFile && event.Has(fsnotify.Remove) {
eventsWG.Done()
return
}
@@ -573,7 +576,7 @@ func (v *Viper) AddConfigPath(in string) {
// AddRemoteProvider adds a remote configuration source.
// Remote Providers are searched in the order they are added.
-// provider is a string value: "etcd", "consul" or "firestore" are currently supported.
+// provider is a string value: "etcd", "etcd3", "consul" or "firestore" are currently supported.
// endpoint is the url. etcd requires http://ip:port consul requires ip:port
// path is the path in the k/v store to retrieve configuration
// To retrieve a config file called myapp.json from /configs/myapp.json
@@ -604,7 +607,7 @@ func (v *Viper) AddRemoteProvider(provider, endpoint, path string) error {
// AddSecureRemoteProvider adds a remote configuration source.
// Secure Remote Providers are searched in the order they are added.
-// provider is a string value: "etcd", "consul" or "firestore" are currently supported.
+// provider is a string value: "etcd", "etcd3", "consul" or "firestore" are currently supported.
// endpoint is the url. etcd requires http://ip:port consul requires ip:port
// secretkeyring is the filepath to your openpgp secret keyring. e.g. /etc/secrets/myring.gpg
// path is the path in the k/v store to retrieve configuration
@@ -785,7 +788,8 @@ func (v *Viper) searchMapWithPathPrefixes(
// isPathShadowedInDeepMap makes sure the given path is not shadowed somewhere
// on its path in the map.
// e.g., if "foo.bar" has a value in the given map, it “shadows”
-// "foo.bar.baz" in a lower-priority map
+//
+// "foo.bar.baz" in a lower-priority map
func (v *Viper) isPathShadowedInDeepMap(path []string, m map[string]interface{}) string {
var parentVal interface{}
for i := 1; i < len(path); i++ {
@@ -810,7 +814,8 @@ func (v *Viper) isPathShadowedInDeepMap(path []string, m map[string]interface{})
// isPathShadowedInFlatMap makes sure the given path is not shadowed somewhere
// in a sub-path of the map.
// e.g., if "foo.bar" has a value in the given map, it “shadows”
-// "foo.bar.baz" in a lower-priority map
+//
+// "foo.bar.baz" in a lower-priority map
func (v *Viper) isPathShadowedInFlatMap(path []string, mi interface{}) string {
// unify input map
var m map[string]interface{}
@@ -835,7 +840,8 @@ func (v *Viper) isPathShadowedInFlatMap(path []string, mi interface{}) string {
// isPathShadowedInAutoEnv makes sure the given path is not shadowed somewhere
// in the environment, when automatic env is on.
// e.g., if "foo.bar" has a value in the environment, it “shadows”
-// "foo.bar.baz" in a lower-priority map
+//
+// "foo.bar.baz" in a lower-priority map
func (v *Viper) isPathShadowedInAutoEnv(path []string) string {
var parentKey string
for i := 1; i < len(path); i++ {
@@ -856,11 +862,11 @@ func (v *Viper) isPathShadowedInAutoEnv(path []string) string {
// would return a string slice for the key if the key's type is inferred by
// the default value and the Get function would return:
//
-// []string {"a", "b", "c"}
+// []string {"a", "b", "c"}
//
// Otherwise the Get function would return:
//
-// "a b c"
+// "a b c"
func SetTypeByDefaultValue(enable bool) { v.SetTypeByDefaultValue(enable) }
func (v *Viper) SetTypeByDefaultValue(enable bool) {
@@ -988,6 +994,13 @@ func (v *Viper) GetUint(key string) uint {
return cast.ToUint(v.Get(key))
}
+// GetUint16 returns the value associated with the key as an unsigned integer.
+func GetUint16(key string) uint16 { return v.GetUint16(key) }
+
+func (v *Viper) GetUint16(key string) uint16 {
+ return cast.ToUint16(v.Get(key))
+}
+
// GetUint32 returns the value associated with the key as an unsigned integer.
func GetUint32(key string) uint32 { return v.GetUint32(key) }
@@ -1137,9 +1150,8 @@ func (v *Viper) BindPFlags(flags *pflag.FlagSet) error {
// BindPFlag binds a specific key to a pflag (as used by cobra).
// Example (where serverCmd is a Cobra instance):
//
-// serverCmd.Flags().Int("port", 1138, "Port to run Application server on")
-// Viper.BindPFlag("port", serverCmd.Flags().Lookup("port"))
-//
+// serverCmd.Flags().Int("port", 1138, "Port to run Application server on")
+// Viper.BindPFlag("port", serverCmd.Flags().Lookup("port"))
func BindPFlag(key string, flag *pflag.Flag) error { return v.BindPFlag(key, flag) }
func (v *Viper) BindPFlag(key string, flag *pflag.Flag) error {
@@ -1870,6 +1882,10 @@ func (v *Viper) getKeyValueConfig() error {
return RemoteConfigError("Enable the remote features by doing a blank import of the viper/remote package: '_ github.com/spf13/viper/remote'")
}
+ if len(v.remoteProviders) == 0 {
+ return RemoteConfigError("No Remote Providers")
+ }
+
for _, rp := range v.remoteProviders {
val, err := v.getRemoteConfig(rp)
if err != nil {
@@ -1896,6 +1912,10 @@ func (v *Viper) getRemoteConfig(provider RemoteProvider) (map[string]interface{}
// Retrieve the first found remote configuration.
func (v *Viper) watchKeyValueConfigOnChannel() error {
+ if len(v.remoteProviders) == 0 {
+ return RemoteConfigError("No Remote Providers")
+ }
+
for _, rp := range v.remoteProviders {
respc, _ := RemoteConfig.WatchChannel(rp)
// Todo: Add quit channel
@@ -1913,9 +1933,15 @@ func (v *Viper) watchKeyValueConfigOnChannel() error {
// Retrieve the first found remote configuration.
func (v *Viper) watchKeyValueConfig() error {
+ if len(v.remoteProviders) == 0 {
+ return RemoteConfigError("No Remote Providers")
+ }
+
for _, rp := range v.remoteProviders {
val, err := v.watchRemoteConfig(rp)
if err != nil {
+ v.logger.Error(fmt.Errorf("watch remote config: %w", err).Error())
+
continue
}
v.kvstore = val
@@ -1958,9 +1984,10 @@ func (v *Viper) AllKeys() []string {
// flattenAndMergeMap recursively flattens the given map into a map[string]bool
// of key paths (used as a set, easier to manipulate than a []string):
-// - each path is merged into a single key string, delimited with v.keyDelim
-// - if a path is shadowed by an earlier value in the initial shadow map,
-// it is skipped.
+// - each path is merged into a single key string, delimited with v.keyDelim
+// - if a path is shadowed by an earlier value in the initial shadow map,
+// it is skipped.
+//
// The resulting set of paths is merged to the given shadow set at the same time.
func (v *Viper) flattenAndMergeMap(shadow map[string]bool, m map[string]interface{}, prefix string) map[string]bool {
if shadow != nil && prefix != "" && shadow[prefix] {
@@ -2111,14 +2138,17 @@ func (v *Viper) getConfigFile() (string, error) {
// Debug prints all configuration registries for debugging
// purposes.
-func Debug() { v.Debug() }
-
-func (v *Viper) Debug() {
- fmt.Printf("Aliases:\n%#v\n", v.aliases)
- fmt.Printf("Override:\n%#v\n", v.override)
- fmt.Printf("PFlags:\n%#v\n", v.pflags)
- fmt.Printf("Env:\n%#v\n", v.env)
- fmt.Printf("Key/Value Store:\n%#v\n", v.kvstore)
- fmt.Printf("Config:\n%#v\n", v.config)
- fmt.Printf("Defaults:\n%#v\n", v.defaults)
+func Debug() { v.Debug() }
+func DebugTo(w io.Writer) { v.DebugTo(w) }
+
+func (v *Viper) Debug() { v.DebugTo(os.Stdout) }
+
+func (v *Viper) DebugTo(w io.Writer) {
+ fmt.Fprintf(w, "Aliases:\n%#v\n", v.aliases)
+ fmt.Fprintf(w, "Override:\n%#v\n", v.override)
+ fmt.Fprintf(w, "PFlags:\n%#v\n", v.pflags)
+ fmt.Fprintf(w, "Env:\n%#v\n", v.env)
+ fmt.Fprintf(w, "Key/Value Store:\n%#v\n", v.kvstore)
+ fmt.Fprintf(w, "Config:\n%#v\n", v.config)
+ fmt.Fprintf(w, "Defaults:\n%#v\n", v.defaults)
}
diff --git a/vendor/github.com/spf13/viper/watch.go b/vendor/github.com/spf13/viper/watch.go
index b5523b8f..1ce84eaf 100644
--- a/vendor/github.com/spf13/viper/watch.go
+++ b/vendor/github.com/spf13/viper/watch.go
@@ -1,5 +1,5 @@
-//go:build !js
-// +build !js
+//go:build darwin || dragonfly || freebsd || openbsd || linux || netbsd || solaris || windows
+// +build darwin dragonfly freebsd openbsd linux netbsd solaris windows
package viper
diff --git a/vendor/github.com/spf13/viper/watch_wasm.go b/vendor/github.com/spf13/viper/watch_unsupported.go
index 8e47e6a9..7e271537 100644
--- a/vendor/github.com/spf13/viper/watch_wasm.go
+++ b/vendor/github.com/spf13/viper/watch_unsupported.go
@@ -1,13 +1,19 @@
-// +build js,wasm
+//go:build appengine || (!darwin && !dragonfly && !freebsd && !openbsd && !linux && !netbsd && !solaris && !windows)
+// +build appengine !darwin,!dragonfly,!freebsd,!openbsd,!linux,!netbsd,!solaris,!windows
package viper
import (
- "errors"
+ "fmt"
+ "runtime"
"github.com/fsnotify/fsnotify"
)
+func newWatcher() (*watcher, error) {
+ return &watcher{}, fmt.Errorf("fsnotify not supported on %s", runtime.GOOS)
+}
+
type watcher struct {
Events chan fsnotify.Event
Errors chan error
@@ -24,7 +30,3 @@ func (*watcher) Add(name string) error {
func (*watcher) Remove(name string) error {
return nil
}
-
-func newWatcher() (*watcher, error) {
- return &watcher{}, errors.New("fsnotify is not supported on WASM")
-}
diff --git a/vendor/github.com/subosito/gotenv/.gitignore b/vendor/github.com/subosito/gotenv/.gitignore
index 2b8d4561..7db37c1d 100644
--- a/vendor/github.com/subosito/gotenv/.gitignore
+++ b/vendor/github.com/subosito/gotenv/.gitignore
@@ -1,3 +1,4 @@
*.test
*.out
annotate.json
+profile.cov
diff --git a/vendor/github.com/subosito/gotenv/.golangci.yaml b/vendor/github.com/subosito/gotenv/.golangci.yaml
new file mode 100644
index 00000000..8c82a762
--- /dev/null
+++ b/vendor/github.com/subosito/gotenv/.golangci.yaml
@@ -0,0 +1,7 @@
+# Options for analysis running.
+run:
+ timeout: 1m
+
+linters-settings:
+ gofmt:
+ simplify: true
diff --git a/vendor/github.com/subosito/gotenv/CHANGELOG.md b/vendor/github.com/subosito/gotenv/CHANGELOG.md
index 24b096b9..757caad2 100644
--- a/vendor/github.com/subosito/gotenv/CHANGELOG.md
+++ b/vendor/github.com/subosito/gotenv/CHANGELOG.md
@@ -1,5 +1,15 @@
# Changelog
+## [1.4.0] - 2022-06-02
+
+### Added
+
+- Add `Marshal` and `Unmarshal` helpers
+
+### Changed
+
+- The CI will now run a linter and the tests on PRs.
+
## [1.3.0] - 2022-05-23
### Added
@@ -41,7 +51,7 @@
### Added
- Supports carriage return in env
-- Handle files with UTF-8 BOM
+- Handle files with UTF-8 BOM
### Changed
diff --git a/vendor/github.com/subosito/gotenv/README.md b/vendor/github.com/subosito/gotenv/README.md
index 3ce9a410..fc9616e3 100644
--- a/vendor/github.com/subosito/gotenv/README.md
+++ b/vendor/github.com/subosito/gotenv/README.md
@@ -28,7 +28,7 @@ Once loaded you can use `os.Getenv()` to get the value of the variable.
Let's say you have `.env` file:
-```
+```sh
APP_ID=1234567
APP_SECRET=abcdef
```
@@ -78,7 +78,6 @@ Besides above functions, `gotenv` also provides another functions that overrides
- `gotenv.OverLoad`
- `gotenv.OverApply`
-
Here's the example of this overrides behavior:
```go
diff --git a/vendor/github.com/subosito/gotenv/gotenv.go b/vendor/github.com/subosito/gotenv/gotenv.go
index c4c1e50e..dc013e1e 100644
--- a/vendor/github.com/subosito/gotenv/gotenv.go
+++ b/vendor/github.com/subosito/gotenv/gotenv.go
@@ -3,10 +3,14 @@ package gotenv
import (
"bufio"
+ "bytes"
"fmt"
"io"
"os"
+ "path/filepath"
"regexp"
+ "sort"
+ "strconv"
"strings"
)
@@ -24,41 +28,31 @@ const (
// Env holds key/value pair of valid environment variable
type Env map[string]string
-/*
-Load is a function to load a file or multiple files and then export the valid variables into environment variables if they do not exist.
-When it's called with no argument, it will load `.env` file on the current path and set the environment variables.
-Otherwise, it will loop over the filenames parameter and set the proper environment variables.
-*/
+// Load is a function to load a file or multiple files and then export the valid variables into environment variables if they do not exist.
+// When it's called with no argument, it will load `.env` file on the current path and set the environment variables.
+// Otherwise, it will loop over the filenames parameter and set the proper environment variables.
func Load(filenames ...string) error {
return loadenv(false, filenames...)
}
-/*
-OverLoad is a function to load a file or multiple files and then export and override the valid variables into environment variables.
-*/
+// OverLoad is a function to load a file or multiple files and then export and override the valid variables into environment variables.
func OverLoad(filenames ...string) error {
return loadenv(true, filenames...)
}
-/*
-Must is wrapper function that will panic when supplied function returns an error.
-*/
+// Must is wrapper function that will panic when supplied function returns an error.
func Must(fn func(filenames ...string) error, filenames ...string) {
if err := fn(filenames...); err != nil {
panic(err.Error())
}
}
-/*
-Apply is a function to load an io Reader then export the valid variables into environment variables if they do not exist.
-*/
+// Apply is a function to load an io Reader then export the valid variables into environment variables if they do not exist.
func Apply(r io.Reader) error {
return parset(r, false)
}
-/*
-OverApply is a function to load an io Reader then export and override the valid variables into environment variables.
-*/
+// OverApply is a function to load an io Reader then export and override the valid variables into environment variables.
func OverApply(r io.Reader) error {
return parset(r, true)
}
@@ -75,11 +69,10 @@ func loadenv(override bool, filenames ...string) error {
}
err = parset(f, override)
+ f.Close()
if err != nil {
return err
}
-
- f.Close()
}
return nil
@@ -124,9 +117,94 @@ func StrictParse(r io.Reader) (Env, error) {
return strictParse(r, false)
}
+// Read is a function to parse a file line by line and returns the valid Env key/value pair of valid variables.
+// It expands the value of a variable from the environment variable but does not set the value to the environment itself.
+// This function is skipping any invalid lines and only processing the valid one.
+func Read(filename string) (Env, error) {
+ f, err := os.Open(filename)
+ if err != nil {
+ return nil, err
+ }
+ defer f.Close()
+ return strictParse(f, false)
+}
+
+// Unmarshal reads a string line by line and returns the valid Env key/value pair of valid variables.
+// It expands the value of a variable from the environment variable but does not set the value to the environment itself.
+// This function is returning an error if there are any invalid lines.
+func Unmarshal(str string) (Env, error) {
+ return strictParse(strings.NewReader(str), false)
+}
+
+// Marshal outputs the given environment as a env file.
+// Variables will be sorted by name.
+func Marshal(env Env) (string, error) {
+ lines := make([]string, 0, len(env))
+ for k, v := range env {
+ if d, err := strconv.Atoi(v); err == nil {
+ lines = append(lines, fmt.Sprintf(`%s=%d`, k, d))
+ } else {
+ lines = append(lines, fmt.Sprintf(`%s=%q`, k, v))
+ }
+ }
+ sort.Strings(lines)
+ return strings.Join(lines, "\n"), nil
+}
+
+// Write serializes the given environment and writes it to a file
+func Write(env Env, filename string) error {
+ content, err := Marshal(env)
+ if err != nil {
+ return err
+ }
+ // ensure the path exists
+ if err := os.MkdirAll(filepath.Dir(filename), 0o775); err != nil {
+ return err
+ }
+ // create or truncate the file
+ file, err := os.Create(filename)
+ if err != nil {
+ return err
+ }
+ defer file.Close()
+ _, err = file.WriteString(content + "\n")
+ if err != nil {
+ return err
+ }
+
+ return file.Sync()
+}
+
+// splitLines is a valid SplitFunc for a bufio.Scanner. It will split lines on CR ('\r'), LF ('\n') or CRLF (any of the three sequences).
+// If a CR is immediately followed by a LF, it is treated as a CRLF (one single line break).
+func splitLines(data []byte, atEOF bool) (advance int, token []byte, err error) {
+ if atEOF && len(data) == 0 {
+ return 0, nil, bufio.ErrFinalToken
+ }
+
+ idx := bytes.IndexAny(data, "\r\n")
+ switch {
+ case atEOF && idx < 0:
+ return len(data), data, bufio.ErrFinalToken
+
+ case idx < 0:
+ return 0, nil, nil
+ }
+
+ // consume CR or LF
+ eol := idx + 1
+ // detect CRLF
+ if len(data) > eol && data[eol-1] == '\r' && data[eol] == '\n' {
+ eol++
+ }
+
+ return eol, data[:idx], nil
+}
+
func strictParse(r io.Reader, override bool) (Env, error) {
env := make(Env)
scanner := bufio.NewScanner(r)
+ scanner.Split(splitLines)
firstLine := true
@@ -143,28 +221,34 @@ func strictParse(r io.Reader, override bool) (Env, error) {
}
quote := ""
+ // look for the delimiter character
idx := strings.Index(line, "=")
if idx == -1 {
idx = strings.Index(line, ":")
}
+ // look for a quote character
if idx > 0 && idx < len(line)-1 {
val := strings.TrimSpace(line[idx+1:])
if val[0] == '"' || val[0] == '\'' {
quote = val[:1]
+ // look for the closing quote character within the same line
idx = strings.LastIndex(strings.TrimSpace(val[1:]), quote)
if idx >= 0 && val[idx] != '\\' {
quote = ""
}
}
}
+ // look for the closing quote character
for quote != "" && scanner.Scan() {
l := scanner.Text()
line += "\n" + l
idx := strings.LastIndex(l, quote)
if idx > 0 && l[idx-1] == '\\' {
+ // foud a matching quote character but it's escaped
continue
}
if idx >= 0 {
+ // foud a matching quote
quote = ""
}
}
@@ -195,21 +279,23 @@ func parseLine(s string, env Env, override bool) error {
return checkFormat(s, env)
}
- key := rm[1]
- val := rm[2]
-
- // trim whitespace
- val = strings.TrimSpace(val)
+ key := strings.TrimSpace(rm[1])
+ val := strings.TrimSpace(rm[2])
- // determine if string has quote prefix
- hdq := strings.HasPrefix(val, `"`)
+ var hsq, hdq bool
- // determine if string has single quote prefix
- hsq := strings.HasPrefix(val, `'`)
+ // check if the value is quoted
+ if l := len(val); l >= 2 {
+ l -= 1
+ // has double quotes
+ hdq = val[0] == '"' && val[l] == '"'
+ // has single quotes
+ hsq = val[0] == '\'' && val[l] == '\''
- // remove quotes '' or ""
- if l := len(val); (hsq || hdq) && l >= 2 {
- val = val[1 : l-1]
+ // remove quotes '' or ""
+ if hsq || hdq {
+ val = val[1:l]
+ }
}
if hdq {
@@ -220,13 +306,11 @@ func parseLine(s string, env Env, override bool) error {
val = unescapeRgx.ReplaceAllString(val, "$1")
}
- fv := func(s string) string {
- return varReplacement(s, hsq, env, override)
- }
-
if !hsq {
+ fv := func(s string) string {
+ return varReplacement(s, hsq, env, override)
+ }
val = varRgx.ReplaceAllStringFunc(val, fv)
- val = parseVal(val, env, hdq, override)
}
env[key] = val
@@ -250,8 +334,13 @@ func parseExport(st string, env Env) error {
var varNameRgx = regexp.MustCompile(`(\$)(\{?([A-Z0-9_]+)\}?)`)
func varReplacement(s string, hsq bool, env Env, override bool) string {
- if strings.HasPrefix(s, "\\") {
- return strings.TrimPrefix(s, "\\")
+ if s == "" {
+ return s
+ }
+
+ if s[0] == '\\' {
+ // the dollar sign is escaped
+ return s[1:]
}
if hsq {
@@ -270,18 +359,17 @@ func varReplacement(s string, hsq bool, env Env, override bool) string {
return replace
}
- replace, ok := env[v]
- if !ok {
- replace = os.Getenv(v)
+ if replace, ok := env[v]; ok {
+ return replace
}
- return replace
+ return os.Getenv(v)
}
func checkFormat(s string, env Env) error {
st := strings.TrimSpace(s)
- if (st == "") || strings.HasPrefix(st, "#") {
+ if st == "" || st[0] == '#' {
return nil
}
@@ -291,18 +379,3 @@ func checkFormat(s string, env Env) error {
return fmt.Errorf("line `%s` doesn't match format", s)
}
-
-func parseVal(val string, env Env, ignoreNewlines bool, override bool) string {
- if strings.Contains(val, "=") && !ignoreNewlines {
- kv := strings.Split(val, "\r")
-
- if len(kv) > 1 {
- val = kv[0]
- for _, l := range kv[1:] {
- _ = parseLine(l, env, override)
- }
- }
- }
-
- return val
-}
diff --git a/vendor/github.com/valyala/fasttemplate/template.go b/vendor/github.com/valyala/fasttemplate/template.go
index 18620013..f2d3261f 100644
--- a/vendor/github.com/valyala/fasttemplate/template.go
+++ b/vendor/github.com/valyala/fasttemplate/template.go
@@ -112,8 +112,7 @@ func ExecuteFuncString(template, startTag, endTag string, f TagFunc) string {
// but when f returns an error, ExecuteFuncStringWithErr won't panic like ExecuteFuncString
// it just returns an empty string and the error f returned
func ExecuteFuncStringWithErr(template, startTag, endTag string, f TagFunc) (string, error) {
- tagsCount := bytes.Count(unsafeString2Bytes(template), unsafeString2Bytes(startTag))
- if tagsCount == 0 {
+ if n := bytes.Index(unsafeString2Bytes(template), unsafeString2Bytes(startTag)); n < 0 {
return template, nil
}