forked from lug/matterbridge
Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
24bc0f127b | ||
|
|
f0f801402d | ||
|
|
663850a2b8 | ||
|
|
c51753cab1 | ||
|
|
b3be2e208c | ||
|
|
c30e90ff3f | ||
|
|
e4c0ca0f48 | ||
|
|
9c203327c0 | ||
|
|
ccb5b1d075 | ||
|
|
0dbbd0414c | ||
|
|
e7b3ebf98a | ||
|
|
5bc18fb780 | ||
|
|
df30366072 |
22
.github/dependabot.yml
vendored
22
.github/dependabot.yml
vendored
@@ -1,22 +0,0 @@
|
||||
# Docs: <https://docs.github.com/en/free-pro-team@latest/github/administering-a-repository/customizing-dependency-updates>
|
||||
|
||||
version: 2
|
||||
|
||||
updates:
|
||||
- package-ecosystem: gomod
|
||||
directory: /
|
||||
schedule: {interval: weekly}
|
||||
reviewers: [42wim]
|
||||
assignees: [42wim]
|
||||
|
||||
- package-ecosystem: github-actions
|
||||
directory: /
|
||||
schedule: {interval: weekly}
|
||||
reviewers: [42wim]
|
||||
assignees: [42wim]
|
||||
|
||||
- package-ecosystem: docker
|
||||
directory: /
|
||||
schedule: {interval: weekly}
|
||||
reviewers: [42wim]
|
||||
assignees: [42wim]
|
||||
@@ -164,7 +164,7 @@ See <https://github.com/42wim/matterbridge/wiki>
|
||||
|
||||
### Binaries
|
||||
|
||||
- Latest stable release [v1.24.0](https://github.com/42wim/matterbridge/releases/latest)
|
||||
- Latest stable release [v1.24.1](https://github.com/42wim/matterbridge/releases/latest)
|
||||
- Development releases (follows master) can be downloaded [here](https://github.com/42wim/matterbridge/actions) selecting the latest green build and then artifacts.
|
||||
|
||||
To install or upgrade just download the latest [binary](https://github.com/42wim/matterbridge/releases/latest). On \*nix platforms you may need to make the binary executable - you can do this by running `chmod a+x` on the binary (example: `chmod a+x matterbridge-1.20.0-linux-64bit`). After downloading (and making the binary executable, if necessary), follow the instructions on the [howto](https://github.com/42wim/matterbridge/wiki/How-to-create-your-config) for a step by step walkthrough for creating your configuration.
|
||||
@@ -185,13 +185,13 @@ Go 1.17+ is required. Make sure you have [Go](https://golang.org/doc/install) pr
|
||||
To install the latest stable run:
|
||||
|
||||
```bash
|
||||
go install github.com/42wim/matterbridge
|
||||
go install github.com/42wim/matterbridge@v1.24.1
|
||||
```
|
||||
|
||||
To install the latest dev run:
|
||||
|
||||
```bash
|
||||
go install github.com/42wim/matterbridge@master
|
||||
go install github.com/42wim/matterbridge@latest
|
||||
```
|
||||
|
||||
You should now have matterbridge binary in the ~/go/bin directory:
|
||||
|
||||
@@ -10,8 +10,8 @@ import (
|
||||
"github.com/42wim/matterbridge/bridge/config"
|
||||
"github.com/42wim/matterbridge/bridge/discord/transmitter"
|
||||
"github.com/42wim/matterbridge/bridge/helper"
|
||||
"github.com/bwmarrin/discordgo"
|
||||
lru "github.com/hashicorp/golang-lru"
|
||||
"github.com/matterbridge/discordgo"
|
||||
)
|
||||
|
||||
const (
|
||||
|
||||
@@ -2,8 +2,8 @@ package bdiscord
|
||||
|
||||
import (
|
||||
"github.com/42wim/matterbridge/bridge/config"
|
||||
"github.com/bwmarrin/discordgo"
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
"github.com/matterbridge/discordgo"
|
||||
)
|
||||
|
||||
func (b *Bdiscord) messageDelete(s *discordgo.Session, m *discordgo.MessageDelete) { //nolint:unparam
|
||||
@@ -56,7 +56,7 @@ func (b *Bdiscord) messageUpdate(s *discordgo.Session, m *discordgo.MessageUpdat
|
||||
return
|
||||
}
|
||||
// only when message is actually edited
|
||||
if m.Message.EditedTimestamp != "" {
|
||||
if m.Message.EditedTimestamp != nil {
|
||||
b.Log.Debugf("Sending edit message")
|
||||
m.Content += b.GetString("EditSuffix")
|
||||
msg := &discordgo.MessageCreate{
|
||||
|
||||
@@ -3,7 +3,7 @@ package bdiscord
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/matterbridge/discordgo"
|
||||
"github.com/bwmarrin/discordgo"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
"strings"
|
||||
"unicode"
|
||||
|
||||
"github.com/matterbridge/discordgo"
|
||||
"github.com/bwmarrin/discordgo"
|
||||
)
|
||||
|
||||
func (b *Bdiscord) getAllowedMentions() *discordgo.MessageAllowedMentions {
|
||||
|
||||
@@ -20,7 +20,7 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/matterbridge/discordgo"
|
||||
"github.com/bwmarrin/discordgo"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package transmitter
|
||||
|
||||
import (
|
||||
"github.com/matterbridge/discordgo"
|
||||
"github.com/bwmarrin/discordgo"
|
||||
)
|
||||
|
||||
// isDiscordPermissionError returns false for nil, and true if a Discord RESTError with code discordgo.ErrorCodeMissionPermissions
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
|
||||
"github.com/42wim/matterbridge/bridge/config"
|
||||
"github.com/42wim/matterbridge/bridge/helper"
|
||||
"github.com/matterbridge/discordgo"
|
||||
"github.com/bwmarrin/discordgo"
|
||||
)
|
||||
|
||||
// shouldMessageUseWebhooks checks if have a channel specific webhook, if we're not using auto webhooks
|
||||
@@ -89,7 +89,7 @@ func (b *Bdiscord) webhookSend(msg *config.Message, channelID string) (*discordg
|
||||
&discordgo.WebhookParams{
|
||||
Username: msg.Username,
|
||||
AvatarURL: msg.Avatar,
|
||||
File: &file,
|
||||
Files: []*discordgo.File{&file},
|
||||
Content: content,
|
||||
AllowedMentions: b.getAllowedMentions(),
|
||||
},
|
||||
|
||||
32
bridge/irc/charset.go
Normal file
32
bridge/irc/charset.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package birc
|
||||
|
||||
import (
|
||||
"golang.org/x/text/encoding"
|
||||
"golang.org/x/text/encoding/japanese"
|
||||
"golang.org/x/text/encoding/korean"
|
||||
"golang.org/x/text/encoding/simplifiedchinese"
|
||||
"golang.org/x/text/encoding/traditionalchinese"
|
||||
"golang.org/x/text/encoding/unicode"
|
||||
)
|
||||
|
||||
var encoders = map[string]encoding.Encoding{
|
||||
"utf-8": unicode.UTF8,
|
||||
"iso-2022-jp": japanese.ISO2022JP,
|
||||
"big5": traditionalchinese.Big5,
|
||||
"gbk": simplifiedchinese.GBK,
|
||||
"euc-kr": korean.EUCKR,
|
||||
"gb2312": simplifiedchinese.HZGB2312,
|
||||
"shift-jis": japanese.ShiftJIS,
|
||||
"euc-jp": japanese.EUCJP,
|
||||
"gb18030": simplifiedchinese.GB18030,
|
||||
}
|
||||
|
||||
func toUTF8(from string, input string) string {
|
||||
enc, ok := encoders[from]
|
||||
if !ok {
|
||||
return input
|
||||
}
|
||||
|
||||
res, _ := enc.NewDecoder().String(input)
|
||||
return res
|
||||
}
|
||||
@@ -11,7 +11,6 @@ import (
|
||||
"github.com/42wim/matterbridge/bridge/config"
|
||||
"github.com/42wim/matterbridge/bridge/helper"
|
||||
"github.com/lrstanley/girc"
|
||||
"github.com/missdeer/golib/ic"
|
||||
"github.com/paulrosania/go-charset/charset"
|
||||
"github.com/saintfish/chardet"
|
||||
|
||||
@@ -24,12 +23,12 @@ func (b *Birc) handleCharset(msg *config.Message) error {
|
||||
if b.GetString("Charset") != "" {
|
||||
switch b.GetString("Charset") {
|
||||
case "gbk", "gb18030", "gb2312", "big5", "euc-kr", "euc-jp", "shift-jis", "iso-2022-jp":
|
||||
msg.Text = ic.ConvertString("utf-8", b.GetString("Charset"), msg.Text)
|
||||
msg.Text = toUTF8(b.GetString("Charset"), msg.Text)
|
||||
default:
|
||||
buf := new(bytes.Buffer)
|
||||
w, err := charset.NewWriter(b.GetString("Charset"), buf)
|
||||
if err != nil {
|
||||
b.Log.Errorf("charset from utf-8 conversion failed: %s", err)
|
||||
b.Log.Errorf("charset to utf-8 conversion failed: %s", err)
|
||||
return err
|
||||
}
|
||||
fmt.Fprint(w, msg.Text)
|
||||
@@ -227,7 +226,7 @@ func (b *Birc) handlePrivMsg(client *girc.Client, event girc.Event) {
|
||||
}
|
||||
switch mycharset {
|
||||
case "gbk", "gb18030", "gb2312", "big5", "euc-kr", "euc-jp", "shift-jis", "iso-2022-jp":
|
||||
rmsg.Text = ic.ConvertString("utf-8", b.GetString("Charset"), rmsg.Text)
|
||||
rmsg.Text = toUTF8(b.GetString("Charset"), rmsg.Text)
|
||||
default:
|
||||
r, err := charset.NewReader(mycharset, strings.NewReader(rmsg.Text))
|
||||
if err != nil {
|
||||
|
||||
@@ -362,8 +362,10 @@ func (b *Birc) skipPrivMsg(event girc.Event) bool {
|
||||
return true
|
||||
}
|
||||
// don't forward message from ourself
|
||||
if event.Source.Name == b.Nick {
|
||||
return true
|
||||
if event.Source != nil {
|
||||
if event.Source.Name == b.Nick {
|
||||
return true
|
||||
}
|
||||
}
|
||||
// don't forward messages we sent via RELAYMSG
|
||||
if relayedNick, ok := event.Tags.Get("draft/relaymsg"); ok && relayedNick == b.Nick {
|
||||
|
||||
70
bridge/mumble/codec.go
Normal file
70
bridge/mumble/codec.go
Normal file
@@ -0,0 +1,70 @@
|
||||
package bmumble
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"layeh.com/gumble/gumble"
|
||||
)
|
||||
|
||||
// This is a dummy implementation of a Gumble audio codec which claims
|
||||
// to implement Opus, but does not actually do anything. This serves
|
||||
// as a workaround until https://github.com/layeh/gumble/pull/61 is
|
||||
// merged.
|
||||
// See https://github.com/42wim/matterbridge/issues/1750 for details.
|
||||
|
||||
const (
|
||||
audioCodecIDOpus = 4
|
||||
)
|
||||
|
||||
func registerNullCodecAsOpus() {
|
||||
codec := &NullCodec{
|
||||
encoder: &NullAudioEncoder{},
|
||||
decoder: &NullAudioDecoder{},
|
||||
}
|
||||
gumble.RegisterAudioCodec(audioCodecIDOpus, codec)
|
||||
}
|
||||
|
||||
type NullCodec struct {
|
||||
encoder *NullAudioEncoder
|
||||
decoder *NullAudioDecoder
|
||||
}
|
||||
|
||||
func (c *NullCodec) ID() int {
|
||||
return audioCodecIDOpus
|
||||
}
|
||||
|
||||
func (c *NullCodec) NewEncoder() gumble.AudioEncoder {
|
||||
e := &NullAudioEncoder{}
|
||||
return e
|
||||
}
|
||||
|
||||
func (c *NullCodec) NewDecoder() gumble.AudioDecoder {
|
||||
d := &NullAudioDecoder{}
|
||||
return d
|
||||
}
|
||||
|
||||
type NullAudioEncoder struct{}
|
||||
|
||||
func (e *NullAudioEncoder) ID() int {
|
||||
return audioCodecIDOpus
|
||||
}
|
||||
|
||||
func (e *NullAudioEncoder) Encode(pcm []int16, mframeSize, maxDataBytes int) ([]byte, error) {
|
||||
return nil, fmt.Errorf("not implemented")
|
||||
}
|
||||
|
||||
func (e *NullAudioEncoder) Reset() {
|
||||
}
|
||||
|
||||
type NullAudioDecoder struct{}
|
||||
|
||||
func (d *NullAudioDecoder) ID() int {
|
||||
return audioCodecIDOpus
|
||||
}
|
||||
|
||||
func (d *NullAudioDecoder) Decode(data []byte, frameSize int) ([]int16, error) {
|
||||
return nil, fmt.Errorf("not implemented")
|
||||
}
|
||||
|
||||
func (d *NullAudioDecoder) Reset() {
|
||||
}
|
||||
@@ -185,6 +185,7 @@ func (b *Bmumble) doConnect() error {
|
||||
gumbleConfig.Password = password
|
||||
}
|
||||
|
||||
registerNullCodecAsOpus()
|
||||
client, err := gumble.DialWithDialer(new(net.Dialer), b.GetString("Server"), gumbleConfig, &b.tlsConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -57,6 +57,11 @@ func (b *Btelegram) handleForwarded(rmsg *config.Message, message *tgbotapi.Mess
|
||||
return
|
||||
}
|
||||
|
||||
if message.ForwardFromChat != nil && message.ForwardFrom == nil {
|
||||
rmsg.Text = "Forwarded from " + message.ForwardFromChat.Title + ": " + rmsg.Text
|
||||
return
|
||||
}
|
||||
|
||||
if message.ForwardFrom == nil {
|
||||
rmsg.Text = "Forwarded from " + unknownUser + ": " + rmsg.Text
|
||||
return
|
||||
@@ -182,6 +187,9 @@ func (b *Btelegram) handleRecv(updates <-chan tgbotapi.Update) {
|
||||
rmsg.ID = strconv.Itoa(message.MessageID)
|
||||
rmsg.Channel = strconv.FormatInt(message.Chat.ID, 10)
|
||||
|
||||
// handle entities (adding URLs)
|
||||
b.handleEntities(&rmsg, message)
|
||||
|
||||
// handle username
|
||||
b.handleUsername(&rmsg, message)
|
||||
|
||||
@@ -197,11 +205,9 @@ func (b *Btelegram) handleRecv(updates <-chan tgbotapi.Update) {
|
||||
// quote the previous message
|
||||
b.handleQuoting(&rmsg, message)
|
||||
|
||||
// handle entities (adding URLs)
|
||||
b.handleEntities(&rmsg, message)
|
||||
|
||||
if rmsg.Text != "" || len(rmsg.Extra) > 0 {
|
||||
rmsg.Text = helper.RemoveEmptyNewLines(rmsg.Text)
|
||||
// Comment the next line out due to avoid removing empty lines in Telegram
|
||||
// rmsg.Text = helper.RemoveEmptyNewLines(rmsg.Text)
|
||||
// channels don't have (always?) user information. see #410
|
||||
if message.From != nil {
|
||||
rmsg.Avatar = helper.GetAvatar(b.avatarMap, strconv.FormatInt(message.From.ID, 10), b.General)
|
||||
@@ -483,31 +489,51 @@ func (b *Btelegram) handleEntities(rmsg *config.Message, message *tgbotapi.Messa
|
||||
|
||||
// for now only do URL replacements
|
||||
for _, e := range message.Entities {
|
||||
|
||||
asRunes := utf16.Encode([]rune(rmsg.Text))
|
||||
|
||||
if e.Type == "text_link" {
|
||||
offset := e.Offset + indexMovedBy
|
||||
url, err := e.ParseURL()
|
||||
if err != nil {
|
||||
b.Log.Errorf("entity text_link url parse failed: %s", err)
|
||||
continue
|
||||
}
|
||||
utfEncodedString := utf16.Encode([]rune(rmsg.Text))
|
||||
if e.Offset+e.Length > len(utfEncodedString) {
|
||||
b.Log.Errorf("entity length is too long %d > %d", e.Offset+e.Length, len(utfEncodedString))
|
||||
if offset+e.Length > len(utfEncodedString) {
|
||||
b.Log.Errorf("entity length is too long %d > %d", offset+e.Length, len(utfEncodedString))
|
||||
continue
|
||||
}
|
||||
link := utf16.Decode(utfEncodedString[e.Offset : e.Offset+e.Length])
|
||||
rmsg.Text = strings.Replace(rmsg.Text, string(link), url.String(), 1)
|
||||
rmsg.Text = string(utf16.Decode(asRunes[:offset+e.Length])) + " (" + url.String() + ")" + string(utf16.Decode(asRunes[offset+e.Length:]))
|
||||
indexMovedBy += len(url.String()) + 3
|
||||
}
|
||||
|
||||
if e.Type == "code" {
|
||||
offset := e.Offset + indexMovedBy
|
||||
rmsg.Text = rmsg.Text[:offset] + "`" + rmsg.Text[offset:offset+e.Length] + "`" + rmsg.Text[offset+e.Length:]
|
||||
rmsg.Text = string(utf16.Decode(asRunes[:offset])) + "`" + string(utf16.Decode(asRunes[offset:offset+e.Length])) + "`" + string(utf16.Decode(asRunes[offset+e.Length:]))
|
||||
indexMovedBy += 2
|
||||
}
|
||||
|
||||
if e.Type == "pre" {
|
||||
offset := e.Offset + indexMovedBy
|
||||
rmsg.Text = rmsg.Text[:offset] + "```\n" + rmsg.Text[offset:offset+e.Length] + "\n```" + rmsg.Text[offset+e.Length:]
|
||||
rmsg.Text = string(utf16.Decode(asRunes[:offset])) + "```\n" + string(utf16.Decode(asRunes[offset:offset+e.Length])) + "```\n" + string(utf16.Decode(asRunes[offset+e.Length:]))
|
||||
indexMovedBy += 8
|
||||
}
|
||||
|
||||
if e.Type == "bold" {
|
||||
offset := e.Offset + indexMovedBy
|
||||
rmsg.Text = string(utf16.Decode(asRunes[:offset])) + "*" + string(utf16.Decode(asRunes[offset:offset+e.Length])) + "*" + string(utf16.Decode(asRunes[offset+e.Length:]))
|
||||
indexMovedBy += 2
|
||||
}
|
||||
if e.Type == "italic" {
|
||||
offset := e.Offset + indexMovedBy
|
||||
rmsg.Text = string(utf16.Decode(asRunes[:offset])) + "_" + string(utf16.Decode(asRunes[offset:offset+e.Length])) + "_" + string(utf16.Decode(asRunes[offset+e.Length:]))
|
||||
indexMovedBy += 2
|
||||
}
|
||||
if e.Type == "strike" {
|
||||
offset := e.Offset + indexMovedBy
|
||||
rmsg.Text = string(utf16.Decode(asRunes[:offset])) + "~" + string(utf16.Decode(asRunes[offset:offset+e.Length])) + "~" + string(utf16.Decode(asRunes[offset+e.Length:]))
|
||||
indexMovedBy += 2
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
30
changelog.md
30
changelog.md
@@ -1,3 +1,24 @@
|
||||
# v1.24.1
|
||||
|
||||
## Enhancements
|
||||
|
||||
- discord: Switch to discordgo upstream again (#1759)
|
||||
- general: Update dependencies and vendor (#1761)
|
||||
- general: Create inmessage-logger.tengo (#1688) (#1747)
|
||||
- general: Add OpenRC service file (#1746)
|
||||
- irc: Refactor utf-8 conversion (irc) (#1767)
|
||||
|
||||
## Bugfixes
|
||||
|
||||
- irc: Fix panic in irc. Closes #1751 (#1760)
|
||||
- mumble: Implement a workaround to signal Opus support (mumble) (#1764)
|
||||
- telegram: Fix for complex-formatted Telegram text (#1765)
|
||||
- telegram: Fix Telegram channel title in forwards (#1753)
|
||||
- telegram: Fix Telegram Problem (unforwarded formatting and skipping of linebreaks) (#1749)
|
||||
|
||||
This release couldn't exist without the following contributors:
|
||||
@s3lph, @ValdikSS, @reckel-jm, @CyberTailor
|
||||
|
||||
# v1.24.0
|
||||
|
||||
## New features
|
||||
@@ -30,6 +51,9 @@
|
||||
- matrix: Make HTMLDisable work correct (matrix) (#1716)
|
||||
- whatsapp: Make EditSuffix option actually work (whatsapp). Fixes #1510 (#1728)
|
||||
|
||||
This release couldn't exist without the following contributors:
|
||||
@DavyJohnesev, @GoliathLabs, @pontaoski, @PeGaSuS-Coder, @dependabot[bot], @vpzomtrrfrt, @SevereCloud, @soloam, @YashRE42, @danwalmsley, @SuperSandro2000, @inzanity
|
||||
|
||||
# v1.23.2
|
||||
|
||||
If you're running whatsapp you should update.
|
||||
@@ -38,6 +62,9 @@ If you're running whatsapp you should update.
|
||||
|
||||
- whatsapp: Update go-whatsapp version (#1630)
|
||||
|
||||
This release couldn't exist without the following contributors:
|
||||
@snikpic
|
||||
|
||||
# v1.23.1
|
||||
|
||||
If you're running mattermost 6 you should update.
|
||||
@@ -52,6 +79,9 @@ If you're running mattermost 6 you should update.
|
||||
- xmpp: Use a new msgID when replacing messages (xmpp). Fixes #1584 (#1623)
|
||||
- zulip: Add better error handling on Zulip (#1589)
|
||||
|
||||
This release couldn't exist without the following contributors:
|
||||
@Polynomdivision, @minecraftchest1, @alexmv
|
||||
|
||||
# v1.23.0
|
||||
|
||||
## New features
|
||||
|
||||
15
contrib/inmessage-logger.tengo
Normal file
15
contrib/inmessage-logger.tengo
Normal file
@@ -0,0 +1,15 @@
|
||||
fmt := import("fmt")
|
||||
os := import("os")
|
||||
times := import("times")
|
||||
|
||||
if msgText != "" && msgUsername != "system" {
|
||||
os.chdir("/var/www/matterbridge")
|
||||
file := os.open_file("inmessage.log", os.o_append|os.o_wronly|os.o_create, 0644)
|
||||
file.write_string(fmt.sprintf(
|
||||
"[%s] <%s> %s\n",
|
||||
times.time_format(times.now(), times.format_rfc1123),
|
||||
msgUsername,
|
||||
msgText
|
||||
))
|
||||
file.close()
|
||||
}
|
||||
19
contrib/matterbridge.openrc
Executable file
19
contrib/matterbridge.openrc
Executable file
@@ -0,0 +1,19 @@
|
||||
#!/sbin/openrc-run
|
||||
# Copyright 2021-2022 Gentoo Authors
|
||||
# Distributed under the terms of the GNU General Public License v2
|
||||
|
||||
command=/usr/bin/matterbridge
|
||||
command_args="-conf ${MATTERBRIDGE_CONF:-/etc/matterbridge/bridge.toml} ${MATTERBRIDGE_ARGS}"
|
||||
command_user="matterbridge:matterbridge"
|
||||
pidfile="/run/${RC_SVCNAME}.pid"
|
||||
command_background=1
|
||||
output_log="/var/log/${RC_SVCNAME}.log"
|
||||
error_log="${output_log}"
|
||||
|
||||
depend() {
|
||||
need net
|
||||
}
|
||||
|
||||
start_pre() {
|
||||
checkpath -f "${output_log}" -o "${command_user}" || return 1
|
||||
}
|
||||
29
go.mod
29
go.mod
@@ -7,32 +7,31 @@ require (
|
||||
github.com/Philipp15b/go-steam v1.0.1-0.20200727090957-6ae9b3c0a560
|
||||
github.com/Rhymen/go-whatsapp v0.1.2-0.20211102134409-31a2e740845c
|
||||
github.com/SevereCloud/vksdk/v2 v2.13.1
|
||||
github.com/d5/tengo/v2 v2.10.0
|
||||
github.com/bwmarrin/discordgo v0.24.0
|
||||
github.com/d5/tengo/v2 v2.10.1
|
||||
github.com/davecgh/go-spew v1.1.1
|
||||
github.com/fsnotify/fsnotify v1.5.1
|
||||
github.com/go-telegram-bot-api/telegram-bot-api/v5 v5.5.1
|
||||
github.com/gomarkdown/markdown v0.0.0-20211207152620-5d6539fd8bfc
|
||||
github.com/gomarkdown/markdown v0.0.0-20220310201231-552c6011c0b8
|
||||
github.com/google/gops v0.3.22
|
||||
github.com/gorilla/schema v1.2.0
|
||||
github.com/gorilla/websocket v1.4.2
|
||||
github.com/harmony-development/shibshib v0.0.0-20211127182844-512296f7c548
|
||||
github.com/gorilla/websocket v1.5.0
|
||||
github.com/harmony-development/shibshib v0.0.0-20220101224523-c98059d09cfa
|
||||
github.com/hashicorp/golang-lru v0.5.4
|
||||
github.com/jpillora/backoff v1.0.0
|
||||
github.com/keybase/go-keybase-chat-bot v0.0.0-20211201215354-ee4b23828b55
|
||||
github.com/kyokomi/emoji/v2 v2.2.8
|
||||
github.com/labstack/echo/v4 v4.6.3
|
||||
github.com/kyokomi/emoji/v2 v2.2.9
|
||||
github.com/labstack/echo/v4 v4.7.0
|
||||
github.com/lrstanley/girc v0.0.0-20211023233735-147f0ff77566
|
||||
github.com/matrix-org/gomatrix v0.0.0-20210324163249-be2af5ef2e16
|
||||
github.com/matterbridge/Rocket.Chat.Go.SDK v0.0.0-20211016222428-79310a412696
|
||||
github.com/matterbridge/discordgo v0.21.2-0.20210201201054-fb39a175b4f7
|
||||
github.com/matterbridge/go-xmpp v0.0.0-20211030125215-791a06c5f1be
|
||||
github.com/matterbridge/gozulipbot v0.0.0-20211023205727-a19d6c1f3b75
|
||||
github.com/matterbridge/logrus-prefixed-formatter v0.5.3-0.20200523233437-d971309a77ba
|
||||
github.com/matterbridge/matterclient v0.0.0-20211107234719-faca3cd42315
|
||||
github.com/mattermost/mattermost-server/v5 v5.39.3
|
||||
github.com/mattermost/mattermost-server/v6 v6.3.0
|
||||
github.com/mattermost/mattermost-server/v6 v6.4.2
|
||||
github.com/mattn/godown v0.0.1
|
||||
github.com/missdeer/golib v1.0.4
|
||||
github.com/nelsonken/gomf v0.0.0-20180504123937-a9dd2f9deae9
|
||||
github.com/paulrosania/go-charset v0.0.0-20190326053356-55c9d7a5834c
|
||||
github.com/rs/xid v1.3.0
|
||||
@@ -40,15 +39,16 @@ require (
|
||||
github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca
|
||||
github.com/shazow/ssh-chat v1.10.1
|
||||
github.com/sirupsen/logrus v1.8.1
|
||||
github.com/slack-go/slack v0.10.0
|
||||
github.com/slack-go/slack v0.10.2
|
||||
github.com/spf13/viper v1.10.1
|
||||
github.com/stretchr/testify v1.7.0
|
||||
github.com/vincent-petithory/dataurl v1.0.0
|
||||
github.com/writeas/go-strip-markdown v2.0.1+incompatible
|
||||
github.com/yaegashi/msgraph.go v0.1.4
|
||||
github.com/zfjagann/golang-ring v0.0.0-20210116075443-7c86fdb43134
|
||||
golang.org/x/image v0.0.0-20211028202545-6944b10bf410
|
||||
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8
|
||||
golang.org/x/image v0.0.0-20220302094943-723b81ca9867
|
||||
golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a
|
||||
golang.org/x/text v0.3.7
|
||||
gomod.garykim.dev/nc-talk v0.3.0
|
||||
gopkg.in/olahol/melody.v1 v1.0.0-20170518105555-d52139073376
|
||||
layeh.com/gumble v0.0.0-20200818122324-146f9205029b
|
||||
@@ -123,10 +123,9 @@ require (
|
||||
go.uber.org/multierr v1.7.0 // indirect
|
||||
go.uber.org/zap v1.17.0 // indirect
|
||||
golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871 // indirect
|
||||
golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9 // indirect
|
||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd // indirect
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e // indirect
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 // indirect
|
||||
golang.org/x/text v0.3.7 // indirect
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
|
||||
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324 // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
google.golang.org/protobuf v1.27.1 // indirect
|
||||
|
||||
81
go.sum
81
go.sum
@@ -54,7 +54,6 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo
|
||||
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
|
||||
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
|
||||
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
|
||||
cloud.google.com/go/storage v1.16.1/go.mod h1:LaNorbty3ehnU3rEjXSNV/NRgQA0O8Y+uh6bPe5UOk4=
|
||||
code.sajari.com/docconv v1.1.1-0.20210427001343-7b3472bc323a/go.mod h1:KPNt2zuWplps1W0TpOb6ltHj4Xu+j6h7a+YkqGHrxQE=
|
||||
code.sajari.com/docconv v1.2.0/go.mod h1:r8yfCP6OKbZ9Xkd87aBa4nfpk6ud/PoyLwex3n6cXSc=
|
||||
contrib.go.opencensus.io/exporter/ocagent v0.4.9/go.mod h1:ueLzZcP7LPhPulEBukGn4aLh7Mx9YJwpVJ9nL2FYltw=
|
||||
@@ -72,7 +71,6 @@ github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOv
|
||||
github.com/Azure/azure-pipeline-go v0.2.3/go.mod h1:x841ezTBIMG6O3lAcl8ATHnsOPVl2bqk7S3ta6S6u4k=
|
||||
github.com/Azure/azure-sdk-for-go v16.2.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
|
||||
github.com/Azure/azure-sdk-for-go v26.5.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
|
||||
github.com/Azure/azure-sdk-for-go v55.3.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
|
||||
github.com/Azure/azure-storage-blob-go v0.14.0/go.mod h1:SMqIBi+SuiQH32bvyjngEewEeXoPfKMgWlBDaYf6fck=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
|
||||
@@ -80,7 +78,6 @@ github.com/Azure/go-autorest v10.8.1+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSW
|
||||
github.com/Azure/go-autorest v11.5.2+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
|
||||
github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
|
||||
github.com/Azure/go-autorest/autorest v0.11.1/go.mod h1:JFgpikqFJ/MleTTxwepExTKnFUKKszPS8UavbQYUMuw=
|
||||
github.com/Azure/go-autorest/autorest v0.11.19/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA=
|
||||
github.com/Azure/go-autorest/autorest/adal v0.9.0/go.mod h1:/c022QCutn2P7uY+/oQWWNcK9YU+MH96NgK+jErpbcg=
|
||||
github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A=
|
||||
github.com/Azure/go-autorest/autorest/adal v0.9.13/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M=
|
||||
@@ -88,7 +85,6 @@ github.com/Azure/go-autorest/autorest/adal v0.9.14/go.mod h1:W/MM4U6nLxnIskrw4Uw
|
||||
github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74=
|
||||
github.com/Azure/go-autorest/autorest/mocks v0.4.0/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k=
|
||||
github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k=
|
||||
github.com/Azure/go-autorest/autorest/to v0.4.0/go.mod h1:fE8iZBn7LQR7zH/9XU2NcPR4o9jEImooCeWJcYV/zLE=
|
||||
github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8=
|
||||
github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8=
|
||||
github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
|
||||
@@ -165,7 +161,6 @@ github.com/advancedlogic/GoOse v0.0.0-20200830213114-1225d531e0ad/go.mod h1:f3HC
|
||||
github.com/advancedlogic/GoOse v0.0.0-20210820140952-9d5822d4a625/go.mod h1:f3HCSN1fBWjcpGtXyM119MJgeQl838v6so/PQOqvE1w=
|
||||
github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY=
|
||||
github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw=
|
||||
github.com/alecthomas/repr v0.0.0-20210801044451-80ca428c5142/go.mod h1:2kn6fqh/zIyPLmm3ugklbEi5hg5wS435eygvNfaDQL8=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
@@ -175,7 +170,6 @@ github.com/alexcesaro/log v0.0.0-20150915221235-61e686294e58/go.mod h1:YNfsMyWSs
|
||||
github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0=
|
||||
github.com/andybalholm/brotli v1.0.0/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
|
||||
github.com/andybalholm/brotli v1.0.1/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
|
||||
github.com/andybalholm/brotli v1.0.2/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
|
||||
github.com/andybalholm/brotli v1.0.3/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
|
||||
github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
|
||||
github.com/andybalholm/cascadia v1.0.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
|
||||
@@ -212,7 +206,6 @@ github.com/aws/aws-sdk-go v1.17.7/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN
|
||||
github.com/aws/aws-sdk-go v1.19.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
|
||||
github.com/aws/aws-sdk-go v1.20.6/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
|
||||
github.com/aws/aws-sdk-go v1.38.67/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro=
|
||||
github.com/aws/aws-sdk-go v1.40.42/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q=
|
||||
github.com/aws/aws-sdk-go v1.42.11/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q=
|
||||
github.com/aws/aws-sdk-go-v2 v1.8.0/go.mod h1:xEFuWz+3TYdlPRuo+CqATbeDWIWyaT5uAPwPaWtgse0=
|
||||
github.com/aws/aws-sdk-go-v2 v1.9.2/go.mod h1:cK/D0BBs0b/oWPIcX/Z/obahJK1TT7IPVjy53i/mX/4=
|
||||
@@ -290,6 +283,8 @@ github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7
|
||||
github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8=
|
||||
github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50=
|
||||
github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE=
|
||||
github.com/bwmarrin/discordgo v0.24.0 h1:Gw4MYxqHdvhO99A3nXnSLy97z5pmIKHZVJ1JY5ZDPqY=
|
||||
github.com/bwmarrin/discordgo v0.24.0/go.mod h1:NJZpH+1AfhIcyQsPeuBKsUtYrRnjkyu0kIVMCHkZtRY=
|
||||
github.com/cenkalti/backoff/v4 v4.0.2/go.mod h1:eEew/i+1Q6OrCDZh3WiXYv3+nJwBASZ8Bog/87DQnVg=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
@@ -450,8 +445,9 @@ github.com/d2g/dhcp4 v0.0.0-20170904100407-a1d1b6c41b1c/go.mod h1:Ct2BUK8SB0YC1S
|
||||
github.com/d2g/dhcp4client v1.0.0/go.mod h1:j0hNfjhrt2SxUOw55nL0ATM/z4Yt3t2Kd1mW34z5W5s=
|
||||
github.com/d2g/dhcp4server v0.0.0-20181031114812-7d4a0a7f59a5/go.mod h1:Eo87+Kg/IX2hfWJfwxMzLyuSZyxSoAug2nGa1G2QAi8=
|
||||
github.com/d2g/hardwareaddr v0.0.0-20190221164911-e7d9fbe030e4/go.mod h1:bMl4RjIciD2oAxI7DmWRx6gbeqrkoLqv3MV0vzNad+I=
|
||||
github.com/d5/tengo/v2 v2.10.0 h1:gR3VwfJDBlffV8WzfSNNJ7WJtWduwbTKlAu14cA2fRs=
|
||||
github.com/d5/tengo/v2 v2.10.0/go.mod h1:XRGjEs5I9jYIKTxly6HCF8oiiilk5E/RYXOZ5b0DZC8=
|
||||
github.com/d5/tengo/v2 v2.10.1 h1:Z7vmTAQfdoExNEB9kxgqxvoBBW9bf+8uYMiDyriX5HM=
|
||||
github.com/d5/tengo/v2 v2.10.1/go.mod h1:XRGjEs5I9jYIKTxly6HCF8oiiilk5E/RYXOZ5b0DZC8=
|
||||
github.com/dave/jennifer v1.4.1/go.mod h1:7jEdnm+qBcxl8PC0zyp7vxcpSRnzXSt9r39tpTVGlwA=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
@@ -469,11 +465,9 @@ github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8
|
||||
github.com/dhui/dktest v0.3.3/go.mod h1:EML9sP4sqJELHn4jV7B0TY8oF6077nk83/tz7M56jcQ=
|
||||
github.com/dhui/dktest v0.3.7/go.mod h1:nYMOkafiA07WchSwKnKFUSbGMb2hMm5DrCGiXYG6gwM=
|
||||
github.com/die-net/lrucache v0.0.0-20181227122439-19a39ef22a11/go.mod h1:ew0MSjCVDdtGMjF3kzLK9hwdgF5mOE8SbYVF3Rc7mkU=
|
||||
github.com/die-net/lrucache v0.0.0-20190707192454-883874fe3947/go.mod h1:KsMcjmY1UCGl7ozPbdVPDOvLaFeXnptSvtNRczhxNto=
|
||||
github.com/disintegration/imaging v1.6.0/go.mod h1:xuIt+sRxDFrHS0drzXUlCJthkJ8k7lkkUojDSR247MQ=
|
||||
github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4=
|
||||
github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E=
|
||||
github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ=
|
||||
github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY=
|
||||
github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||
@@ -523,15 +517,13 @@ github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c/go.mod h1:Yg+htX
|
||||
github.com/facebookgo/stack v0.0.0-20160209184415-751773369052/go.mod h1:UbMTZqLaRiH3MsBH8va0n7s1pQYcu3uTb8G4tygF4Zg=
|
||||
github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4/go.mod h1:5tD+neXqOorC30/tWg0LCSkrqj/AR6gu8yY8/fpw1q0=
|
||||
github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8=
|
||||
github.com/fasthttp/websocket v1.4.3-rc.9/go.mod h1:eXL2zqDbexYJxaCw8/PQlm7VcMK6uoGvwbYbTdt4dFo=
|
||||
github.com/fasthttp/websocket v1.4.3-rc.10/go.mod h1:xU7SHrziVFuFx3IO24nLKcu4tm3QykCFXhwtwRk9Xd0=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
|
||||
github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
|
||||
github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
|
||||
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
|
||||
github.com/fatih/set v0.2.1/go.mod h1:+RKtMCH+favT2+3YecHGxcc0b4KyVWA1QWWJUs4E0CI=
|
||||
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
|
||||
github.com/fcjr/aia-transport-go v1.2.2/go.mod h1:onSqSq3tGkM14WusDx7q9FTheS9R1KBtD+QBWI6zG/w=
|
||||
github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/felixge/httpsnoop v1.0.2/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
|
||||
@@ -588,6 +580,7 @@ github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG
|
||||
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
|
||||
github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
|
||||
github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8=
|
||||
github.com/go-morph/morph v0.2.3-0.20220126093237-74bffc135498/go.mod h1:XQh5WcM351wOV3z3zEWRM8RaJ65E2p4P7WWbmFAi8x4=
|
||||
github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||
github.com/go-ole/go-ole v1.2.6-0.20210915003542-8b1f7f90f6b1/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||
github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg=
|
||||
@@ -650,8 +643,6 @@ github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c/go.mod h1:/YcGZj5zSblf
|
||||
github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4=
|
||||
github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/gofiber/fiber/v2 v2.20.1/go.mod h1:/LdZHMUXZvTTo7gU4+b1hclqCAdoQphNQ9bi9gutPyI=
|
||||
github.com/gofiber/websocket/v2 v2.0.12/go.mod h1:lQRy0u5ACJfiez/e/bhGeYvM0/M940Y3NFw14U3/otI=
|
||||
github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
||||
github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
||||
github.com/gogo/googleapis v1.2.0/go.mod h1:Njal3psf3qN6dwBtQfUmBZh2ybovJ0tlu3o/AC7HYjU=
|
||||
@@ -711,8 +702,8 @@ github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEW
|
||||
github.com/golang/snappy v0.0.2/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/gomarkdown/markdown v0.0.0-20211207152620-5d6539fd8bfc h1:mmMAHzJGtMsCaDyRgPNMO6cbSzeKCZxHTA1Sn/wirko=
|
||||
github.com/gomarkdown/markdown v0.0.0-20211207152620-5d6539fd8bfc/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA=
|
||||
github.com/gomarkdown/markdown v0.0.0-20220310201231-552c6011c0b8 h1:YVvt637ygnOO9qjLBVmPOvrUmCz/i8YECSu/8UlOQW0=
|
||||
github.com/gomarkdown/markdown v0.0.0-20220310201231-552c6011c0b8/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA=
|
||||
github.com/gomodule/redigo v1.7.1-0.20190724094224-574c33c3df38/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4=
|
||||
github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4=
|
||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
@@ -794,8 +785,9 @@ github.com/gorilla/schema v1.2.0/go.mod h1:kgLaKoK1FELgZqMAVxx/5cbj0kT+57qxUrAlI
|
||||
github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
|
||||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
|
||||
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
|
||||
github.com/gregjones/httpcache v0.0.0-20190212212710-3befbb6ad0cc/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
|
||||
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
|
||||
@@ -811,9 +803,8 @@ github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFb
|
||||
github.com/h2non/go-is-svg v0.0.0-20160927212452-35e8c4b0612c/go.mod h1:ObS/W+h8RYb1Y7fYivughjxojTmIu5iAIjSrSLCLeqE=
|
||||
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4=
|
||||
github.com/hako/durafmt v0.0.0-20210608085754-5c1018a4e16b/go.mod h1:VzxiSdG6j1pi7rwGm/xYI5RbtpBgM8sARDXlvEvxlu0=
|
||||
github.com/harmony-development/hrpc v0.0.0-20211020182021-788fc204a0fe/go.mod h1:B+5b0+n0UpMtqAGtJ2oYlgsArI9LbSJ0/HoySJNzDFY=
|
||||
github.com/harmony-development/shibshib v0.0.0-20211127182844-512296f7c548 h1:jAnKjA+wco4ONGpCtINd0t+sC+ffF+yYScGqgJ2OG4o=
|
||||
github.com/harmony-development/shibshib v0.0.0-20211127182844-512296f7c548/go.mod h1:e3LPbk9jFYwu72EVyGPJC7CKBBSmxb4ZdyJalaaskdc=
|
||||
github.com/harmony-development/shibshib v0.0.0-20220101224523-c98059d09cfa h1:0EefSRfsNrdEwmoGVz4+cMG8++5M2XhvJ1tTRmmrJu8=
|
||||
github.com/harmony-development/shibshib v0.0.0-20220101224523-c98059d09cfa/go.mod h1:+KEOMb29OC2kRa5BajwNM2NEjHTbQA/Z3gKYARLHREI=
|
||||
github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
|
||||
github.com/hashicorp/consul/api v1.12.0/go.mod h1:6pVBMo0ebnYdt2S3H87XhekM/HHrUoTD2XXb/VrZVy0=
|
||||
github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
|
||||
@@ -1038,11 +1029,11 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/ktrysmt/go-bitbucket v0.6.4/go.mod h1:9u0v3hsd2rqCHRIpbir1oP7F58uo5dq19sBYvuMoyQ4=
|
||||
github.com/kyokomi/emoji/v2 v2.2.8 h1:jcofPxjHWEkJtkIbcLHvZhxKgCPl6C7MyjTrD4KDqUE=
|
||||
github.com/kyokomi/emoji/v2 v2.2.8/go.mod h1:JUcn42DTdsXJo1SWanHh4HKDEyPaR5CqkmoirZZP9qE=
|
||||
github.com/kyokomi/emoji/v2 v2.2.9 h1:UWYkjplPZ4rMPvLxc+/e12/xTqoRcn55oUySkpZ554g=
|
||||
github.com/kyokomi/emoji/v2 v2.2.9/go.mod h1:JUcn42DTdsXJo1SWanHh4HKDEyPaR5CqkmoirZZP9qE=
|
||||
github.com/labstack/echo/v4 v4.1.11/go.mod h1:i541M3Fj6f76NZtHSj7TXnyM8n2gaodfvfxNnFqi74g=
|
||||
github.com/labstack/echo/v4 v4.6.3 h1:VhPuIZYxsbPmo4m9KAkMU/el2442eB7EBFFhNTTT9ac=
|
||||
github.com/labstack/echo/v4 v4.6.3/go.mod h1:Hk5OiHj0kDqmFq7aHe7eDqI7CUhuCrfpupQtLGGLm7A=
|
||||
github.com/labstack/echo/v4 v4.7.0 h1:8wHgZhoE9OT1NSLw6sfrX7ZGpWMtO5Zlfr68+BIo180=
|
||||
github.com/labstack/echo/v4 v4.7.0/go.mod h1:xkCDAdFCIf8jsFQ5NnbK7oqaF/yU1A1X20Ltm0OvSks=
|
||||
github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k=
|
||||
github.com/labstack/gommon v0.3.1 h1:OomWaJXm7xR6L1HmEtGyQf26TEn7V6X88mktX9kee9o=
|
||||
github.com/labstack/gommon v0.3.1/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM=
|
||||
@@ -1079,8 +1070,6 @@ github.com/marstr/guid v0.0.0-20170427235115-8bdf7d1a087c/go.mod h1:74gB1z2wpxxI
|
||||
github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho=
|
||||
github.com/matterbridge/Rocket.Chat.Go.SDK v0.0.0-20211016222428-79310a412696 h1:pmPKkN3RJM9wVMZidR99epzK0+gatQiqVtvP1FacZcQ=
|
||||
github.com/matterbridge/Rocket.Chat.Go.SDK v0.0.0-20211016222428-79310a412696/go.mod h1:c6MxwqHD+0HvtAJjsHMIdPCiAwGiQwPRPTp69ACMg8A=
|
||||
github.com/matterbridge/discordgo v0.21.2-0.20210201201054-fb39a175b4f7 h1:4J2YZuY8dIYrxbLMsWGqPZb/B59ygCwSBkyZHez5PSY=
|
||||
github.com/matterbridge/discordgo v0.21.2-0.20210201201054-fb39a175b4f7/go.mod h1:411nZYv0UMMrtppR5glXop1foboJiFAowy+42U+Ahvw=
|
||||
github.com/matterbridge/go-xmpp v0.0.0-20211030125215-791a06c5f1be h1:zlirT+LngOJ60G6FVzI87DljGZLUnfNzmXja61EjtYM=
|
||||
github.com/matterbridge/go-xmpp v0.0.0-20211030125215-791a06c5f1be/go.mod h1:ECDRehsR9TYTKCAsRS8/wLeOk6UUqDydw47ln7wG41Q=
|
||||
github.com/matterbridge/gomatrix v0.0.0-20220205235239-607eb9ee6419 h1:dx8x2J3EsVwP3hBGNmVT/otz4b42p7TRQ6Cu4BK2910=
|
||||
@@ -1108,8 +1097,8 @@ github.com/mattermost/logr/v2 v2.0.15/go.mod h1:mpPp935r5dIkFDo2y9Q87cQWhFR/4xXp
|
||||
github.com/mattermost/mattermost-server/v5 v5.39.3 h1:A5z/NlR4Xcwxx5UnlaNgUGP5hgj4KOV/CwpFg3OtlvQ=
|
||||
github.com/mattermost/mattermost-server/v5 v5.39.3/go.mod h1:MDmVSmsSsqwNkuZ7rQ0osuXVCzrR1IUqGR7I0QU91sY=
|
||||
github.com/mattermost/mattermost-server/v6 v6.0.0/go.mod h1:+S8CsNEPv1FOl1usaPBQ6Gu9+Sm1Cc9YdU/Qh1YMGVI=
|
||||
github.com/mattermost/mattermost-server/v6 v6.3.0 h1:wxUBvu6whm2FAMm5n2J4xbchtrSndRW3g3VQnGt8KPw=
|
||||
github.com/mattermost/mattermost-server/v6 v6.3.0/go.mod h1:L9gIoi9ESBh/NefsaZCfOVBMnbhx+v3kXhInGt3DQmA=
|
||||
github.com/mattermost/mattermost-server/v6 v6.4.2 h1:UyrYoBYrV7dB7JWSEOPXKZaTyYZE2PRDysqx/54ayng=
|
||||
github.com/mattermost/mattermost-server/v6 v6.4.2/go.mod h1:5dOl/bx4N9iTytZ4p44xfGiOiZelbdap42FbEjmN+FU=
|
||||
github.com/mattermost/rsc v0.0.0-20160330161541-bbaefb05eaa0/go.mod h1:nV5bfVpT//+B1RPD2JvRnxbkLmJEYXmRaaVl15fsXjs=
|
||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
|
||||
@@ -1174,8 +1163,6 @@ github.com/minio/minio-go/v7 v7.0.16/go.mod h1:pUV0Pc+hPd1nccgmzQF/EXh48l/Z/yps6
|
||||
github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM=
|
||||
github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g=
|
||||
github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM=
|
||||
github.com/missdeer/golib v1.0.4 h1:tM7MJIPffXSmwFCTOCMjL5C7JsT5SQ+OmZwzssZQOa8=
|
||||
github.com/missdeer/golib v1.0.4/go.mod h1:mPN/UcszFq0GxKfQsZI3aFOiRjnzXCBZ392od3guGEY=
|
||||
github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4=
|
||||
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
|
||||
github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI=
|
||||
@@ -1208,7 +1195,6 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN
|
||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8=
|
||||
github.com/monaco-io/request v1.0.5 h1:QAJb5m1pCPZUGv3zzTZn7GlQI3q+uJWi7fH9QxDGbm4=
|
||||
github.com/monaco-io/request v1.0.5/go.mod h1:EmggwHktBsbJmCgwZXqy7o0H1NNsAstQBWZrFVd3xtQ=
|
||||
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
|
||||
@@ -1449,7 +1435,6 @@ github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca h1:NugYot0LIVPxT
|
||||
github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca/go.mod h1:uugorj2VCxiV1x+LzaIdVa9b4S4qGAcH6cbhh4qVxOU=
|
||||
github.com/satori/go.uuid v0.0.0-20180103174451-36e9d2ebbde5/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
|
||||
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
|
||||
github.com/savsgio/gotils v0.0.0-20210921075833-21a6215cb0e4/go.mod h1:oejLrk1Y/5zOF+c/aHtXqn3TFlzzbAgPWg8zBiAHDas=
|
||||
github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g=
|
||||
github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw=
|
||||
github.com/scylladb/termtables v0.0.0-20191203121021-c4c0b6d42ff4/go.mod h1:C1a7PQSMz9NShzorzCiG2fk9+xuCgLkPeCvMHYR2OWg=
|
||||
@@ -1506,8 +1491,8 @@ github.com/sizeofint/webpanimation v0.0.0-20210809145948-1d2b32119882 h1:A7o8tOE
|
||||
github.com/sizeofint/webpanimation v0.0.0-20210809145948-1d2b32119882/go.mod h1:5IwJoz9Pw7JsrCN4/skkxUtSWT7myuUPLhCgv6Q5vvQ=
|
||||
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0=
|
||||
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M=
|
||||
github.com/slack-go/slack v0.10.0 h1:L16Eqg3QZzRKGXIVsFSZdJdygjOphb2FjRUwH6VrFu8=
|
||||
github.com/slack-go/slack v0.10.0/go.mod h1:wWL//kk0ho+FcQXcBTmEafUI5dz4qz5f4mMk8oIkioQ=
|
||||
github.com/slack-go/slack v0.10.2 h1:KMN/h2sgUninHXvQI8PrR/PHBUuWp2NPvz2Kr66tki4=
|
||||
github.com/slack-go/slack v0.10.2/go.mod h1:5FLdBRv7VW/d9EBxx/eEktOptWygbA9K2QK/KW7ds1s=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||
github.com/smartystreets/assertions v1.0.0 h1:UVQPSSmc3qtTi+zPPkCXvZX9VvW/xT/NsRvKfwY81a8=
|
||||
github.com/smartystreets/assertions v1.0.0/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM=
|
||||
@@ -1628,14 +1613,10 @@ github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKn
|
||||
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||
github.com/valyala/fasthttp v1.6.0/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBnvPM1Su9w=
|
||||
github.com/valyala/fasthttp v1.29.0/go.mod h1:2rsYD01CKFrjjsvFxx75KlEUNpWNBY9JWD3K/7o2Cus=
|
||||
github.com/valyala/fasthttp v1.30.0/go.mod h1:2rsYD01CKFrjjsvFxx75KlEUNpWNBY9JWD3K/7o2Cus=
|
||||
github.com/valyala/fasthttp v1.31.0/go.mod h1:2rsYD01CKFrjjsvFxx75KlEUNpWNBY9JWD3K/7o2Cus=
|
||||
github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
|
||||
github.com/valyala/fasttemplate v1.2.1 h1:TVEnxayobAdVkhQfrfes2IzOB6o+z4roRkPF52WA1u4=
|
||||
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
|
||||
github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio=
|
||||
github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
|
||||
github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU=
|
||||
github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM=
|
||||
github.com/vincent-petithory/dataurl v1.0.0 h1:cXw+kPto8NLuJtlMsI152irrVw9fRDX8AbShPRpg2CI=
|
||||
@@ -1791,7 +1772,7 @@ golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPh
|
||||
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201216223049-8b5274cf687f/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
|
||||
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
@@ -1825,8 +1806,9 @@ golang.org/x/image v0.0.0-20200618115811-c13761719519/go.mod h1:FeLwcggjj3mMvU+o
|
||||
golang.org/x/image v0.0.0-20201208152932-35266b937fa6/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/image v0.0.0-20210216034530-4410531fe030/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/image v0.0.0-20210622092929-e6eecd499c2c/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM=
|
||||
golang.org/x/image v0.0.0-20211028202545-6944b10bf410 h1:hTftEOvwiOq2+O8k2D5/Q7COC7k5Qcrgc2TFURJYnvQ=
|
||||
golang.org/x/image v0.0.0-20211028202545-6944b10bf410/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM=
|
||||
golang.org/x/image v0.0.0-20220302094943-723b81ca9867 h1:TcHcE0vrmgzNH1v3ppjcMGbhG5+9fMuvOmUYwNEF4q4=
|
||||
golang.org/x/image v0.0.0-20220302094943-723b81ca9867/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM=
|
||||
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20181217174547-8f45f776aaf1/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
@@ -1924,18 +1906,18 @@ golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy
|
||||
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
|
||||
golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210505024714-0287a6fb4125/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210913180222-943fd674d43e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210916014120-12bc252f5db8/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211013171255-e13a2654a71e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211029224645-99673261e6eb/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9 h1:0qxwC5n+ttVOINCBeRHO0nq9X7uy8SDsPoi5OaCdIEI=
|
||||
golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd h1:O7DYs+zxREGLKzKoMQrtrEacpb0ZVXA5rIwylE2Xchk=
|
||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/oauth2 v0.0.0-20180227000427-d7d64896b5ff/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
@@ -1958,8 +1940,9 @@ golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ
|
||||
golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 h1:RerP+noqYHUQ8CMRcPlC2nvTa4dcBIjegkuWdcUDuqg=
|
||||
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a h1:qfl7ob3DIEs3Ml9oLuPwY2N04gymzAW04WsUQHIClgM=
|
||||
golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
|
||||
golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@@ -2076,6 +2059,7 @@ golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210326220804-49726bf1d181/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@@ -2105,8 +2089,9 @@ golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e h1:fLOSk5Q00efkSvAm+4xcoXD+RRmLmmulPn5I3Y9F2EM=
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
@@ -2347,7 +2332,6 @@ google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKr
|
||||
google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48=
|
||||
google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w=
|
||||
google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
|
||||
google.golang.org/genproto v0.0.0-20210825212027-de86158e7fda/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
|
||||
google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
|
||||
google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
|
||||
google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
|
||||
@@ -2554,4 +2538,3 @@ sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2
|
||||
sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0=
|
||||
willnorris.com/go/gifresize v1.0.0/go.mod h1:eBM8gogBGCcaH603vxSpnfjwXIpq6nmnj/jauBDKtAk=
|
||||
willnorris.com/go/imageproxy v0.10.0/go.mod h1:2tWdKRneln3E9X/zwH1RINpQAQWPeUiNynZ7UQ9OROk=
|
||||
willnorris.com/go/imageproxy v0.11.2/go.mod h1:pyA05z6P0nLWX6QmeqMUyK6v9HnWE/bqnPnrzUST0KU=
|
||||
|
||||
5
vendor/github.com/bwmarrin/discordgo/.gitignore
generated
vendored
Normal file
5
vendor/github.com/bwmarrin/discordgo/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
# IDE-specific metadata
|
||||
.idea/
|
||||
|
||||
# Environment variables. Useful for examples.
|
||||
.env
|
||||
19
vendor/github.com/bwmarrin/discordgo/.golangci.yml
generated
vendored
Normal file
19
vendor/github.com/bwmarrin/discordgo/.golangci.yml
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
linters:
|
||||
disable-all: true
|
||||
enable:
|
||||
# - staticcheck
|
||||
# - unused
|
||||
- golint
|
||||
|
||||
linters-settings:
|
||||
staticcheck:
|
||||
go: "1.13"
|
||||
|
||||
checks: ["all"]
|
||||
|
||||
unused:
|
||||
go: "1.13"
|
||||
|
||||
issues:
|
||||
include:
|
||||
- EXC0002
|
||||
@@ -3,6 +3,7 @@ go:
|
||||
- 1.13.x
|
||||
- 1.14.x
|
||||
- 1.15.x
|
||||
- 1.16.x
|
||||
env:
|
||||
- GO111MODULE=on
|
||||
install:
|
||||
@@ -1,8 +1,8 @@
|
||||
# DiscordGo
|
||||
|
||||
[](https://godoc.org/github.com/bwmarrin/discordgo) [](http://goreportcard.com/report/bwmarrin/discordgo) [](https://travis-ci.org/bwmarrin/discordgo) [](https://discord.gg/0f1SbxBZjYoCtNPP) [](https://discord.com/invite/discord-api)
|
||||
[](https://pkg.go.dev/github.com/bwmarrin/discordgo) [](https://goreportcard.com/report/github.com/bwmarrin/discordgo) [](https://travis-ci.com/bwmarrin/discordgo) [](https://discord.gg/golang) [](https://discord.com/invite/discord-api)
|
||||
|
||||
<img align="right" src="http://bwmarrin.github.io/discordgo/img/discordgo.png">
|
||||
<img align="right" alt="DiscordGo logo" src="docs/img/discordgo.svg" width="400">
|
||||
|
||||
DiscordGo is a [Go](https://golang.org/) package that provides low level
|
||||
bindings to the [Discord](https://discord.com/) chat client API. DiscordGo
|
||||
@@ -22,7 +22,7 @@ tool that wraps `ffmpeg` to create opus encoded audio appropriate for use with
|
||||
Discord (and DiscordGo).
|
||||
|
||||
**For help with this package or general Go discussion, please join the [Discord
|
||||
Gophers](https://discord.gg/0f1SbxBZjYq9jLBk) chat server.**
|
||||
Gophers](https://discord.gg/golang) chat server.**
|
||||
|
||||
## Getting Started
|
||||
|
||||
@@ -64,8 +64,8 @@ The DiscordGo code is fairly well documented at this point and is currently
|
||||
the only documentation available. Both GoDoc and GoWalker (below) present
|
||||
that information in a nice format.
|
||||
|
||||
- [](https://godoc.org/github.com/bwmarrin/discordgo)
|
||||
- [](https://gowalker.org/github.com/bwmarrin/discordgo)
|
||||
- [](https://pkg.go.dev/github.com/bwmarrin/discordgo)
|
||||
- [](https://gowalker.org/github.com/bwmarrin/discordgo)
|
||||
- Hand crafted documentation coming eventually.
|
||||
|
||||
|
||||
241
vendor/github.com/bwmarrin/discordgo/components.go
generated
vendored
Normal file
241
vendor/github.com/bwmarrin/discordgo/components.go
generated
vendored
Normal file
@@ -0,0 +1,241 @@
|
||||
package discordgo
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// ComponentType is type of component.
|
||||
type ComponentType uint
|
||||
|
||||
// MessageComponent types.
|
||||
const (
|
||||
ActionsRowComponent ComponentType = 1
|
||||
ButtonComponent ComponentType = 2
|
||||
SelectMenuComponent ComponentType = 3
|
||||
TextInputComponent ComponentType = 4
|
||||
)
|
||||
|
||||
// MessageComponent is a base interface for all message components.
|
||||
type MessageComponent interface {
|
||||
json.Marshaler
|
||||
Type() ComponentType
|
||||
}
|
||||
|
||||
type unmarshalableMessageComponent struct {
|
||||
MessageComponent
|
||||
}
|
||||
|
||||
// UnmarshalJSON is a helper function to unmarshal MessageComponent object.
|
||||
func (umc *unmarshalableMessageComponent) UnmarshalJSON(src []byte) error {
|
||||
var v struct {
|
||||
Type ComponentType `json:"type"`
|
||||
}
|
||||
err := json.Unmarshal(src, &v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch v.Type {
|
||||
case ActionsRowComponent:
|
||||
umc.MessageComponent = &ActionsRow{}
|
||||
case ButtonComponent:
|
||||
umc.MessageComponent = &Button{}
|
||||
case SelectMenuComponent:
|
||||
umc.MessageComponent = &SelectMenu{}
|
||||
case TextInputComponent:
|
||||
umc.MessageComponent = &TextInput{}
|
||||
default:
|
||||
return fmt.Errorf("unknown component type: %d", v.Type)
|
||||
}
|
||||
return json.Unmarshal(src, umc.MessageComponent)
|
||||
}
|
||||
|
||||
// MessageComponentFromJSON is a helper function for unmarshaling message components
|
||||
func MessageComponentFromJSON(b []byte) (MessageComponent, error) {
|
||||
var u unmarshalableMessageComponent
|
||||
err := u.UnmarshalJSON(b)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal into MessageComponent: %w", err)
|
||||
}
|
||||
return u.MessageComponent, nil
|
||||
}
|
||||
|
||||
// ActionsRow is a container for components within one row.
|
||||
type ActionsRow struct {
|
||||
Components []MessageComponent `json:"components"`
|
||||
}
|
||||
|
||||
// MarshalJSON is a method for marshaling ActionsRow to a JSON object.
|
||||
func (r ActionsRow) MarshalJSON() ([]byte, error) {
|
||||
type actionsRow ActionsRow
|
||||
|
||||
return json.Marshal(struct {
|
||||
actionsRow
|
||||
Type ComponentType `json:"type"`
|
||||
}{
|
||||
actionsRow: actionsRow(r),
|
||||
Type: r.Type(),
|
||||
})
|
||||
}
|
||||
|
||||
// UnmarshalJSON is a helper function to unmarshal Actions Row.
|
||||
func (r *ActionsRow) UnmarshalJSON(data []byte) error {
|
||||
var v struct {
|
||||
RawComponents []unmarshalableMessageComponent `json:"components"`
|
||||
}
|
||||
err := json.Unmarshal(data, &v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
r.Components = make([]MessageComponent, len(v.RawComponents))
|
||||
for i, v := range v.RawComponents {
|
||||
r.Components[i] = v.MessageComponent
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// Type is a method to get the type of a component.
|
||||
func (r ActionsRow) Type() ComponentType {
|
||||
return ActionsRowComponent
|
||||
}
|
||||
|
||||
// ButtonStyle is style of button.
|
||||
type ButtonStyle uint
|
||||
|
||||
// Button styles.
|
||||
const (
|
||||
// PrimaryButton is a button with blurple color.
|
||||
PrimaryButton ButtonStyle = 1
|
||||
// SecondaryButton is a button with grey color.
|
||||
SecondaryButton ButtonStyle = 2
|
||||
// SuccessButton is a button with green color.
|
||||
SuccessButton ButtonStyle = 3
|
||||
// DangerButton is a button with red color.
|
||||
DangerButton ButtonStyle = 4
|
||||
// LinkButton is a special type of button which navigates to a URL. Has grey color.
|
||||
LinkButton ButtonStyle = 5
|
||||
)
|
||||
|
||||
// ComponentEmoji represents button emoji, if it does have one.
|
||||
type ComponentEmoji struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
ID string `json:"id,omitempty"`
|
||||
Animated bool `json:"animated,omitempty"`
|
||||
}
|
||||
|
||||
// Button represents button component.
|
||||
type Button struct {
|
||||
Label string `json:"label"`
|
||||
Style ButtonStyle `json:"style"`
|
||||
Disabled bool `json:"disabled"`
|
||||
Emoji ComponentEmoji `json:"emoji"`
|
||||
|
||||
// NOTE: Only button with LinkButton style can have link. Also, URL is mutually exclusive with CustomID.
|
||||
URL string `json:"url,omitempty"`
|
||||
CustomID string `json:"custom_id,omitempty"`
|
||||
}
|
||||
|
||||
// MarshalJSON is a method for marshaling Button to a JSON object.
|
||||
func (b Button) MarshalJSON() ([]byte, error) {
|
||||
type button Button
|
||||
|
||||
if b.Style == 0 {
|
||||
b.Style = PrimaryButton
|
||||
}
|
||||
|
||||
return json.Marshal(struct {
|
||||
button
|
||||
Type ComponentType `json:"type"`
|
||||
}{
|
||||
button: button(b),
|
||||
Type: b.Type(),
|
||||
})
|
||||
}
|
||||
|
||||
// Type is a method to get the type of a component.
|
||||
func (Button) Type() ComponentType {
|
||||
return ButtonComponent
|
||||
}
|
||||
|
||||
// SelectMenuOption represents an option for a select menu.
|
||||
type SelectMenuOption struct {
|
||||
Label string `json:"label,omitempty"`
|
||||
Value string `json:"value"`
|
||||
Description string `json:"description"`
|
||||
Emoji ComponentEmoji `json:"emoji"`
|
||||
// Determines whenever option is selected by default or not.
|
||||
Default bool `json:"default"`
|
||||
}
|
||||
|
||||
// SelectMenu represents select menu component.
|
||||
type SelectMenu struct {
|
||||
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"`
|
||||
// This value determines the minimal amount of selected items in the menu.
|
||||
MinValues *int `json:"min_values,omitempty"`
|
||||
// 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"`
|
||||
Disabled bool `json:"disabled"`
|
||||
}
|
||||
|
||||
// Type is a method to get the type of a component.
|
||||
func (SelectMenu) Type() ComponentType {
|
||||
return SelectMenuComponent
|
||||
}
|
||||
|
||||
// MarshalJSON is a method for marshaling SelectMenu to a JSON object.
|
||||
func (m SelectMenu) MarshalJSON() ([]byte, error) {
|
||||
type selectMenu SelectMenu
|
||||
|
||||
return json.Marshal(struct {
|
||||
selectMenu
|
||||
Type ComponentType `json:"type"`
|
||||
}{
|
||||
selectMenu: selectMenu(m),
|
||||
Type: m.Type(),
|
||||
})
|
||||
}
|
||||
|
||||
// TextInput represents text input component.
|
||||
type TextInput struct {
|
||||
CustomID string `json:"custom_id"`
|
||||
Label string `json:"label"`
|
||||
Style TextInputStyle `json:"style"`
|
||||
Placeholder string `json:"placeholder,omitempty"`
|
||||
Value string `json:"value,omitempty"`
|
||||
Required bool `json:"required,omitempty"`
|
||||
MinLength int `json:"min_length,omitempty"`
|
||||
MaxLength int `json:"max_length,omitempty"`
|
||||
}
|
||||
|
||||
// Type is a method to get the type of a component.
|
||||
func (TextInput) Type() ComponentType {
|
||||
return TextInputComponent
|
||||
}
|
||||
|
||||
// MarshalJSON is a method for marshaling TextInput to a JSON object.
|
||||
func (m TextInput) MarshalJSON() ([]byte, error) {
|
||||
type inputText TextInput
|
||||
|
||||
return json.Marshal(struct {
|
||||
inputText
|
||||
Type ComponentType `json:"type"`
|
||||
}{
|
||||
inputText: inputText(m),
|
||||
Type: m.Type(),
|
||||
})
|
||||
}
|
||||
|
||||
// TextInputStyle is style of text in TextInput component.
|
||||
type TextInputStyle uint
|
||||
|
||||
// Text styles
|
||||
const (
|
||||
TextInputShort TextInputStyle = 1
|
||||
TextInputParagraph TextInputStyle = 2
|
||||
)
|
||||
60
vendor/github.com/bwmarrin/discordgo/discord.go
generated
vendored
Normal file
60
vendor/github.com/bwmarrin/discordgo/discord.go
generated
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
// Discordgo - Discord bindings for Go
|
||||
// Available at https://github.com/bwmarrin/discordgo
|
||||
|
||||
// Copyright 2015-2016 Bruce Marriner <bruce@sqls.net>. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This file contains high level helper functions and easy entry points for the
|
||||
// entire discordgo package. These functions are being developed and are very
|
||||
// experimental at this point. They will most likely change so please use the
|
||||
// low level functions if that's a problem.
|
||||
|
||||
// Package discordgo provides Discord binding for Go
|
||||
package discordgo
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"runtime"
|
||||
"time"
|
||||
)
|
||||
|
||||
// VERSION of DiscordGo, follows Semantic Versioning. (http://semver.org/)
|
||||
const VERSION = "0.24.0"
|
||||
|
||||
// New creates a new Discord session with provided token.
|
||||
// If the token is for a bot, it must be prefixed with "Bot "
|
||||
// e.g. "Bot ..."
|
||||
// Or if it is an OAuth2 token, it must be prefixed with "Bearer "
|
||||
// e.g. "Bearer ..."
|
||||
func New(token string) (s *Session, err error) {
|
||||
|
||||
// Create an empty Session interface.
|
||||
s = &Session{
|
||||
State: NewState(),
|
||||
Ratelimiter: NewRatelimiter(),
|
||||
StateEnabled: true,
|
||||
Compress: true,
|
||||
ShouldReconnectOnError: true,
|
||||
ShardID: 0,
|
||||
ShardCount: 1,
|
||||
MaxRestRetries: 3,
|
||||
Client: &http.Client{Timeout: (20 * time.Second)},
|
||||
UserAgent: "DiscordBot (https://github.com/bwmarrin/discordgo, v" + VERSION + ")",
|
||||
sequence: new(int64),
|
||||
LastHeartbeatAck: time.Now().UTC(),
|
||||
}
|
||||
|
||||
// Initilize the Identify Package with defaults
|
||||
// These can be modified prior to calling Open()
|
||||
s.Identify.Compress = true
|
||||
s.Identify.LargeThreshold = 250
|
||||
s.Identify.GuildSubscriptions = true
|
||||
s.Identify.Properties.OS = runtime.GOOS
|
||||
s.Identify.Properties.Browser = "DiscordGo v" + VERSION
|
||||
s.Identify.Intents = IntentsAllWithoutPrivileged
|
||||
s.Identify.Token = token
|
||||
s.Token = token
|
||||
|
||||
return
|
||||
}
|
||||
210
vendor/github.com/bwmarrin/discordgo/endpoints.go
generated
vendored
Normal file
210
vendor/github.com/bwmarrin/discordgo/endpoints.go
generated
vendored
Normal file
@@ -0,0 +1,210 @@
|
||||
// Discordgo - Discord bindings for Go
|
||||
// Available at https://github.com/bwmarrin/discordgo
|
||||
|
||||
// Copyright 2015-2016 Bruce Marriner <bruce@sqls.net>. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This file contains variables for all known Discord end points. All functions
|
||||
// throughout the Discordgo package use these variables for all connections
|
||||
// to Discord. These are all exported and you may modify them if needed.
|
||||
|
||||
package discordgo
|
||||
|
||||
import "strconv"
|
||||
|
||||
// APIVersion is the Discord API version used for the REST and Websocket API.
|
||||
var APIVersion = "9"
|
||||
|
||||
// Known Discord API Endpoints.
|
||||
var (
|
||||
EndpointStatus = "https://status.discord.com/api/v2/"
|
||||
EndpointSm = EndpointStatus + "scheduled-maintenances/"
|
||||
EndpointSmActive = EndpointSm + "active.json"
|
||||
EndpointSmUpcoming = EndpointSm + "upcoming.json"
|
||||
|
||||
EndpointDiscord = "https://discord.com/"
|
||||
EndpointAPI = EndpointDiscord + "api/v" + APIVersion + "/"
|
||||
EndpointGuilds = EndpointAPI + "guilds/"
|
||||
EndpointChannels = EndpointAPI + "channels/"
|
||||
EndpointUsers = EndpointAPI + "users/"
|
||||
EndpointGateway = EndpointAPI + "gateway"
|
||||
EndpointGatewayBot = EndpointGateway + "/bot"
|
||||
EndpointWebhooks = EndpointAPI + "webhooks/"
|
||||
EndpointStickers = EndpointAPI + "stickers/"
|
||||
|
||||
EndpointCDN = "https://cdn.discordapp.com/"
|
||||
EndpointCDNAttachments = EndpointCDN + "attachments/"
|
||||
EndpointCDNAvatars = EndpointCDN + "avatars/"
|
||||
EndpointCDNIcons = EndpointCDN + "icons/"
|
||||
EndpointCDNSplashes = EndpointCDN + "splashes/"
|
||||
EndpointCDNChannelIcons = EndpointCDN + "channel-icons/"
|
||||
EndpointCDNBanners = EndpointCDN + "banners/"
|
||||
EndpointCDNGuilds = EndpointCDN + "guilds/"
|
||||
|
||||
EndpointVoice = EndpointAPI + "/voice/"
|
||||
EndpointVoiceRegions = EndpointVoice + "regions"
|
||||
|
||||
// TODO: EndpointUserGuildMember
|
||||
|
||||
EndpointUser = func(uID string) string { return EndpointUsers + uID }
|
||||
EndpointUserAvatar = func(uID, aID string) string { return EndpointCDNAvatars + uID + "/" + aID + ".png" }
|
||||
EndpointUserAvatarAnimated = func(uID, aID string) string { return EndpointCDNAvatars + uID + "/" + aID + ".gif" }
|
||||
EndpointDefaultUserAvatar = func(uDiscriminator string) string {
|
||||
uDiscriminatorInt, _ := strconv.Atoi(uDiscriminator)
|
||||
return EndpointCDN + "embed/avatars/" + strconv.Itoa(uDiscriminatorInt%5) + ".png"
|
||||
}
|
||||
EndpointUserBanner = func(uID, cID string) string {
|
||||
return EndpointCDNBanners + uID + "/" + cID + ".png"
|
||||
}
|
||||
EndpointUserBannerAnimated = func(uID, cID string) string {
|
||||
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 }
|
||||
EndpointUserChannels = func(uID string) string { return EndpointUsers + uID + "/channels" }
|
||||
EndpointUserConnections = func(uID string) string { return EndpointUsers + uID + "/connections" }
|
||||
|
||||
EndpointGuild = func(gID string) string { return EndpointGuilds + gID }
|
||||
EndpointGuildThreads = func(gID string) string { return EndpointGuild(gID) + "/threads" }
|
||||
EndpointGuildActiveThreads = func(gID string) string { return EndpointGuildThreads(gID) + "/active" }
|
||||
EndpointGuildPreview = func(gID string) string { return EndpointGuilds + gID + "/preview" }
|
||||
EndpointGuildChannels = func(gID string) string { return EndpointGuilds + gID + "/channels" }
|
||||
EndpointGuildMembers = func(gID string) string { return EndpointGuilds + gID + "/members" }
|
||||
EndpointGuildMember = func(gID, uID string) string { return EndpointGuilds + gID + "/members/" + uID }
|
||||
EndpointGuildMemberRole = func(gID, uID, rID string) string { return EndpointGuilds + gID + "/members/" + uID + "/roles/" + rID }
|
||||
EndpointGuildBans = func(gID string) string { return EndpointGuilds + gID + "/bans" }
|
||||
EndpointGuildBan = func(gID, uID string) string { return EndpointGuilds + gID + "/bans/" + uID }
|
||||
EndpointGuildIntegrations = func(gID string) string { return EndpointGuilds + gID + "/integrations" }
|
||||
EndpointGuildIntegration = func(gID, iID string) string { return EndpointGuilds + gID + "/integrations/" + iID }
|
||||
EndpointGuildRoles = func(gID string) string { return EndpointGuilds + gID + "/roles" }
|
||||
EndpointGuildRole = func(gID, rID string) string { return EndpointGuilds + gID + "/roles/" + rID }
|
||||
EndpointGuildInvites = func(gID string) string { return EndpointGuilds + gID + "/invites" }
|
||||
EndpointGuildWidget = func(gID string) string { return EndpointGuilds + gID + "/widget" }
|
||||
EndpointGuildEmbed = EndpointGuildWidget
|
||||
EndpointGuildPrune = func(gID string) string { return EndpointGuilds + gID + "/prune" }
|
||||
EndpointGuildIcon = func(gID, hash string) string { return EndpointCDNIcons + gID + "/" + hash + ".png" }
|
||||
EndpointGuildIconAnimated = func(gID, hash string) string { return EndpointCDNIcons + gID + "/" + hash + ".gif" }
|
||||
EndpointGuildSplash = func(gID, hash string) string { return EndpointCDNSplashes + gID + "/" + hash + ".png" }
|
||||
EndpointGuildWebhooks = func(gID string) string { return EndpointGuilds + gID + "/webhooks" }
|
||||
EndpointGuildAuditLogs = func(gID string) string { return EndpointGuilds + gID + "/audit-logs" }
|
||||
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" }
|
||||
EndpointGuildStickers = func(gID string) string { return EndpointGuilds + gID + "/stickers" }
|
||||
EndpointGuildSticker = func(gID, sID string) string { return EndpointGuilds + gID + "/stickers/" + sID }
|
||||
EndpointGuildScheduledEvents = func(gID string) string { return EndpointGuilds + gID + "/scheduled-events" }
|
||||
EndpointGuildScheduledEvent = func(gID, eID string) string { return EndpointGuilds + gID + "/scheduled-events/" + eID }
|
||||
EndpointGuildScheduledEventUsers = func(gID, eID string) string { return EndpointGuildScheduledEvent(gID, eID) + "/users" }
|
||||
EndpointGuildTemplate = func(tID string) string { return EndpointGuilds + "/templates/" + tID }
|
||||
EndpointGuildTemplates = func(gID string) string { return EndpointGuilds + gID + "/templates" }
|
||||
EndpointGuildTemplateSync = func(gID, tID string) string { return EndpointGuilds + gID + "/templates/" + tID }
|
||||
EndpointGuildMemberAvatar = func(gId, uID, aID string) string {
|
||||
return EndpointCDNGuilds + gId + "/users/" + uID + "/avatars/" + aID + ".png"
|
||||
}
|
||||
EndpointGuildMemberAvatarAnimated = func(gId, uID, aID string) string {
|
||||
return EndpointCDNGuilds + gId + "/users/" + uID + "/avatars/" + aID + ".gif"
|
||||
}
|
||||
|
||||
EndpointChannel = func(cID string) string { return EndpointChannels + cID }
|
||||
EndpointChannelThreads = func(cID string) string { return EndpointChannel(cID) + "/threads" }
|
||||
EndpointChannelActiveThreads = func(cID string) string { return EndpointChannelThreads(cID) + "/active" }
|
||||
EndpointChannelPublicArchivedThreads = func(cID string) string { return EndpointChannelThreads(cID) + "/archived/public" }
|
||||
EndpointChannelPrivateArchivedThreads = func(cID string) string { return EndpointChannelThreads(cID) + "/archived/private" }
|
||||
EndpointChannelJoinedPrivateArchivedThreads = func(cID string) string { return EndpointChannel(cID) + "/users/@me/threads/archived/private" }
|
||||
EndpointChannelPermissions = func(cID string) string { return EndpointChannels + cID + "/permissions" }
|
||||
EndpointChannelPermission = func(cID, tID string) string { return EndpointChannels + cID + "/permissions/" + tID }
|
||||
EndpointChannelInvites = func(cID string) string { return EndpointChannels + cID + "/invites" }
|
||||
EndpointChannelTyping = func(cID string) string { return EndpointChannels + cID + "/typing" }
|
||||
EndpointChannelMessages = func(cID string) string { return EndpointChannels + cID + "/messages" }
|
||||
EndpointChannelMessage = func(cID, mID string) string { return EndpointChannels + cID + "/messages/" + mID }
|
||||
EndpointChannelMessageThread = func(cID, mID string) string { return EndpointChannelMessage(cID, mID) + "/threads" }
|
||||
EndpointChannelMessagesBulkDelete = func(cID string) string { return EndpointChannel(cID) + "/messages/bulk-delete" }
|
||||
EndpointChannelMessagesPins = func(cID string) string { return EndpointChannel(cID) + "/pins" }
|
||||
EndpointChannelMessagePin = func(cID, mID string) string { return EndpointChannel(cID) + "/pins/" + mID }
|
||||
EndpointChannelMessageCrosspost = func(cID, mID string) string { return EndpointChannel(cID) + "/messages/" + mID + "/crosspost" }
|
||||
EndpointChannelFollow = func(cID string) string { return EndpointChannel(cID) + "/followers" }
|
||||
EndpointThreadMembers = func(tID string) string { return EndpointChannel(tID) + "/thread-members" }
|
||||
EndpointThreadMember = func(tID, mID string) string { return EndpointThreadMembers(tID) + "/" + mID }
|
||||
|
||||
EndpointGroupIcon = func(cID, hash string) string { return EndpointCDNChannelIcons + cID + "/" + hash + ".png" }
|
||||
|
||||
EndpointSticker = func(sID string) string { return EndpointStickers + sID }
|
||||
EndpointNitroStickersPacks = EndpointAPI + "/sticker-packs"
|
||||
|
||||
EndpointChannelWebhooks = func(cID string) string { return EndpointChannel(cID) + "/webhooks" }
|
||||
EndpointWebhook = func(wID string) string { return EndpointWebhooks + wID }
|
||||
EndpointWebhookToken = func(wID, token string) string { return EndpointWebhooks + wID + "/" + token }
|
||||
EndpointWebhookMessage = func(wID, token, messageID string) string {
|
||||
return EndpointWebhookToken(wID, token) + "/messages/" + messageID
|
||||
}
|
||||
|
||||
EndpointMessageReactionsAll = func(cID, mID string) string {
|
||||
return EndpointChannelMessage(cID, mID) + "/reactions"
|
||||
}
|
||||
EndpointMessageReactions = func(cID, mID, eID string) string {
|
||||
return EndpointChannelMessage(cID, mID) + "/reactions/" + eID
|
||||
}
|
||||
EndpointMessageReaction = func(cID, mID, eID, uID string) string {
|
||||
return EndpointMessageReactions(cID, mID, eID) + "/" + uID
|
||||
}
|
||||
|
||||
EndpointApplicationGlobalCommands = func(aID string) string {
|
||||
return EndpointApplication(aID) + "/commands"
|
||||
}
|
||||
EndpointApplicationGlobalCommand = func(aID, cID string) string {
|
||||
return EndpointApplicationGlobalCommands(aID) + "/" + cID
|
||||
}
|
||||
|
||||
EndpointApplicationGuildCommands = func(aID, gID string) string {
|
||||
return EndpointApplication(aID) + "/guilds/" + gID + "/commands"
|
||||
}
|
||||
EndpointApplicationGuildCommand = func(aID, gID, cID string) string {
|
||||
return EndpointApplicationGuildCommands(aID, gID) + "/" + cID
|
||||
}
|
||||
EndpointApplicationCommandPermissions = func(aID, gID, cID string) string {
|
||||
return EndpointApplicationGuildCommand(aID, gID, cID) + "/permissions"
|
||||
}
|
||||
EndpointApplicationCommandsGuildPermissions = func(aID, gID string) string {
|
||||
return EndpointApplicationGuildCommands(aID, gID) + "/permissions"
|
||||
}
|
||||
EndpointInteraction = func(aID, iToken string) string {
|
||||
return EndpointAPI + "interactions/" + aID + "/" + iToken
|
||||
}
|
||||
EndpointInteractionResponse = func(iID, iToken string) string {
|
||||
return EndpointInteraction(iID, iToken) + "/callback"
|
||||
}
|
||||
EndpointInteractionResponseActions = func(aID, iToken string) string {
|
||||
return EndpointWebhookMessage(aID, iToken, "@original")
|
||||
}
|
||||
EndpointFollowupMessage = func(aID, iToken string) string {
|
||||
return EndpointWebhookToken(aID, iToken)
|
||||
}
|
||||
EndpointFollowupMessageActions = func(aID, iToken, mID string) string {
|
||||
return EndpointWebhookMessage(aID, iToken, mID)
|
||||
}
|
||||
|
||||
EndpointGuildCreate = EndpointAPI + "guilds"
|
||||
|
||||
EndpointInvite = func(iID string) string { return EndpointAPI + "invites/" + iID }
|
||||
|
||||
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 }
|
||||
|
||||
EndpointOAuth2 = EndpointAPI + "oauth2/"
|
||||
EndpointOAuth2Applications = EndpointOAuth2 + "applications"
|
||||
EndpointOAuth2Application = func(aID string) string { return EndpointOAuth2Applications + "/" + aID }
|
||||
EndpointOAuth2ApplicationsBot = func(aID string) string { return EndpointOAuth2Applications + "/" + aID + "/bot" }
|
||||
EndpointOAuth2ApplicationAssets = func(aID string) string { return EndpointOAuth2Applications + "/" + aID + "/assets" }
|
||||
|
||||
// TODO: Deprecated, remove in the next release
|
||||
EndpointOauth2 = EndpointOAuth2
|
||||
EndpointOauth2Applications = EndpointOAuth2Applications
|
||||
EndpointOauth2Application = EndpointOAuth2Application
|
||||
EndpointOauth2ApplicationsBot = EndpointOAuth2ApplicationsBot
|
||||
EndpointOauth2ApplicationAssets = EndpointOAuth2ApplicationAssets
|
||||
)
|
||||
@@ -157,7 +157,7 @@ func (s *Session) removeEventHandlerInstance(t string, ehi *eventHandlerInstance
|
||||
onceHandlers := s.onceHandlers[t]
|
||||
for i := range onceHandlers {
|
||||
if onceHandlers[i] == ehi {
|
||||
s.onceHandlers[t] = append(onceHandlers[:i], handlers[i+1:]...)
|
||||
s.onceHandlers[t] = append(onceHandlers[:i], onceHandlers[i+1:]...)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,50 +7,62 @@ package discordgo
|
||||
// Event type values are used to match the events returned by Discord.
|
||||
// EventTypes surrounded by __ are synthetic and are internal to DiscordGo.
|
||||
const (
|
||||
channelCreateEventType = "CHANNEL_CREATE"
|
||||
channelDeleteEventType = "CHANNEL_DELETE"
|
||||
channelPinsUpdateEventType = "CHANNEL_PINS_UPDATE"
|
||||
channelUpdateEventType = "CHANNEL_UPDATE"
|
||||
connectEventType = "__CONNECT__"
|
||||
disconnectEventType = "__DISCONNECT__"
|
||||
eventEventType = "__EVENT__"
|
||||
guildBanAddEventType = "GUILD_BAN_ADD"
|
||||
guildBanRemoveEventType = "GUILD_BAN_REMOVE"
|
||||
guildCreateEventType = "GUILD_CREATE"
|
||||
guildDeleteEventType = "GUILD_DELETE"
|
||||
guildEmojisUpdateEventType = "GUILD_EMOJIS_UPDATE"
|
||||
guildIntegrationsUpdateEventType = "GUILD_INTEGRATIONS_UPDATE"
|
||||
guildMemberAddEventType = "GUILD_MEMBER_ADD"
|
||||
guildMemberRemoveEventType = "GUILD_MEMBER_REMOVE"
|
||||
guildMemberUpdateEventType = "GUILD_MEMBER_UPDATE"
|
||||
guildMembersChunkEventType = "GUILD_MEMBERS_CHUNK"
|
||||
guildRoleCreateEventType = "GUILD_ROLE_CREATE"
|
||||
guildRoleDeleteEventType = "GUILD_ROLE_DELETE"
|
||||
guildRoleUpdateEventType = "GUILD_ROLE_UPDATE"
|
||||
guildUpdateEventType = "GUILD_UPDATE"
|
||||
messageAckEventType = "MESSAGE_ACK"
|
||||
messageCreateEventType = "MESSAGE_CREATE"
|
||||
messageDeleteEventType = "MESSAGE_DELETE"
|
||||
messageDeleteBulkEventType = "MESSAGE_DELETE_BULK"
|
||||
messageReactionAddEventType = "MESSAGE_REACTION_ADD"
|
||||
messageReactionRemoveEventType = "MESSAGE_REACTION_REMOVE"
|
||||
messageReactionRemoveAllEventType = "MESSAGE_REACTION_REMOVE_ALL"
|
||||
messageUpdateEventType = "MESSAGE_UPDATE"
|
||||
presenceUpdateEventType = "PRESENCE_UPDATE"
|
||||
presencesReplaceEventType = "PRESENCES_REPLACE"
|
||||
rateLimitEventType = "__RATE_LIMIT__"
|
||||
readyEventType = "READY"
|
||||
relationshipAddEventType = "RELATIONSHIP_ADD"
|
||||
relationshipRemoveEventType = "RELATIONSHIP_REMOVE"
|
||||
resumedEventType = "RESUMED"
|
||||
typingStartEventType = "TYPING_START"
|
||||
userGuildSettingsUpdateEventType = "USER_GUILD_SETTINGS_UPDATE"
|
||||
userNoteUpdateEventType = "USER_NOTE_UPDATE"
|
||||
userSettingsUpdateEventType = "USER_SETTINGS_UPDATE"
|
||||
userUpdateEventType = "USER_UPDATE"
|
||||
voiceServerUpdateEventType = "VOICE_SERVER_UPDATE"
|
||||
voiceStateUpdateEventType = "VOICE_STATE_UPDATE"
|
||||
webhooksUpdateEventType = "WEBHOOKS_UPDATE"
|
||||
channelCreateEventType = "CHANNEL_CREATE"
|
||||
channelDeleteEventType = "CHANNEL_DELETE"
|
||||
channelPinsUpdateEventType = "CHANNEL_PINS_UPDATE"
|
||||
channelUpdateEventType = "CHANNEL_UPDATE"
|
||||
connectEventType = "__CONNECT__"
|
||||
disconnectEventType = "__DISCONNECT__"
|
||||
eventEventType = "__EVENT__"
|
||||
guildBanAddEventType = "GUILD_BAN_ADD"
|
||||
guildBanRemoveEventType = "GUILD_BAN_REMOVE"
|
||||
guildCreateEventType = "GUILD_CREATE"
|
||||
guildDeleteEventType = "GUILD_DELETE"
|
||||
guildEmojisUpdateEventType = "GUILD_EMOJIS_UPDATE"
|
||||
guildIntegrationsUpdateEventType = "GUILD_INTEGRATIONS_UPDATE"
|
||||
guildMemberAddEventType = "GUILD_MEMBER_ADD"
|
||||
guildMemberRemoveEventType = "GUILD_MEMBER_REMOVE"
|
||||
guildMemberUpdateEventType = "GUILD_MEMBER_UPDATE"
|
||||
guildMembersChunkEventType = "GUILD_MEMBERS_CHUNK"
|
||||
guildRoleCreateEventType = "GUILD_ROLE_CREATE"
|
||||
guildRoleDeleteEventType = "GUILD_ROLE_DELETE"
|
||||
guildRoleUpdateEventType = "GUILD_ROLE_UPDATE"
|
||||
guildUpdateEventType = "GUILD_UPDATE"
|
||||
guildScheduledEventCreateEventType = "GUILD_SCHEDULED_EVENT_CREATE"
|
||||
guildScheduledEventUpdateEventType = "GUILD_SCHEDULED_EVENT_UPDATE"
|
||||
guildScheduledEventDeleteEventType = "GUILD_SCHEDULED_EVENT_DELETE"
|
||||
interactionCreateEventType = "INTERACTION_CREATE"
|
||||
inviteCreateEventType = "INVITE_CREATE"
|
||||
inviteDeleteEventType = "INVITE_DELETE"
|
||||
messageAckEventType = "MESSAGE_ACK"
|
||||
messageCreateEventType = "MESSAGE_CREATE"
|
||||
messageDeleteEventType = "MESSAGE_DELETE"
|
||||
messageDeleteBulkEventType = "MESSAGE_DELETE_BULK"
|
||||
messageReactionAddEventType = "MESSAGE_REACTION_ADD"
|
||||
messageReactionRemoveEventType = "MESSAGE_REACTION_REMOVE"
|
||||
messageReactionRemoveAllEventType = "MESSAGE_REACTION_REMOVE_ALL"
|
||||
messageUpdateEventType = "MESSAGE_UPDATE"
|
||||
presenceUpdateEventType = "PRESENCE_UPDATE"
|
||||
presencesReplaceEventType = "PRESENCES_REPLACE"
|
||||
rateLimitEventType = "__RATE_LIMIT__"
|
||||
readyEventType = "READY"
|
||||
relationshipAddEventType = "RELATIONSHIP_ADD"
|
||||
relationshipRemoveEventType = "RELATIONSHIP_REMOVE"
|
||||
resumedEventType = "RESUMED"
|
||||
threadCreateEventType = "THREAD_CREATE"
|
||||
threadDeleteEventType = "THREAD_DELETE"
|
||||
threadListSyncEventType = "THREAD_LIST_SYNC"
|
||||
threadMemberUpdateEventType = "THREAD_MEMBER_UPDATE"
|
||||
threadMembersUpdateEventType = "THREAD_MEMBERS_UPDATE"
|
||||
threadUpdateEventType = "THREAD_UPDATE"
|
||||
typingStartEventType = "TYPING_START"
|
||||
userGuildSettingsUpdateEventType = "USER_GUILD_SETTINGS_UPDATE"
|
||||
userNoteUpdateEventType = "USER_NOTE_UPDATE"
|
||||
userSettingsUpdateEventType = "USER_SETTINGS_UPDATE"
|
||||
userUpdateEventType = "USER_UPDATE"
|
||||
voiceServerUpdateEventType = "VOICE_SERVER_UPDATE"
|
||||
voiceStateUpdateEventType = "VOICE_STATE_UPDATE"
|
||||
webhooksUpdateEventType = "WEBHOOKS_UPDATE"
|
||||
)
|
||||
|
||||
// channelCreateEventHandler is an event handler for ChannelCreate events.
|
||||
@@ -298,6 +310,66 @@ func (eh guildIntegrationsUpdateEventHandler) Handle(s *Session, i interface{})
|
||||
}
|
||||
}
|
||||
|
||||
// guildScheduledEventCreateEventHandler is an event handler for GuildScheduledEventCreate events.
|
||||
type guildScheduledEventCreateEventHandler func(*Session, *GuildScheduledEventCreate)
|
||||
|
||||
// Type returns the event type for GuildScheduledEventCreate events.
|
||||
func (eh guildScheduledEventCreateEventHandler) Type() string {
|
||||
return guildScheduledEventCreateEventType
|
||||
}
|
||||
|
||||
// New returns a new instance of GuildScheduledEventCreate.
|
||||
func (eh guildScheduledEventCreateEventHandler) New() interface{} {
|
||||
return &GuildScheduledEventCreate{}
|
||||
}
|
||||
|
||||
// Handle is the handler for GuildScheduledEventCreate events.
|
||||
func (eh guildScheduledEventCreateEventHandler) Handle(s *Session, i interface{}) {
|
||||
if t, ok := i.(*GuildScheduledEventCreate); ok {
|
||||
eh(s, t)
|
||||
}
|
||||
}
|
||||
|
||||
// guildScheduledEventUpdateEventHandler is an event handler for GuildScheduledEventUpdate events.
|
||||
type guildScheduledEventUpdateEventHandler func(*Session, *GuildScheduledEventUpdate)
|
||||
|
||||
// Type returns the event type for GuildScheduledEventUpdate events.
|
||||
func (eh guildScheduledEventUpdateEventHandler) Type() string {
|
||||
return guildScheduledEventUpdateEventType
|
||||
}
|
||||
|
||||
// New returns a new instance of GuildScheduledEventUpdate.
|
||||
func (eh guildScheduledEventUpdateEventHandler) New() interface{} {
|
||||
return &GuildScheduledEventUpdate{}
|
||||
}
|
||||
|
||||
// Handle is the handler for GuildScheduledEventUpdate events.
|
||||
func (eh guildScheduledEventUpdateEventHandler) Handle(s *Session, i interface{}) {
|
||||
if t, ok := i.(*GuildScheduledEventUpdate); ok {
|
||||
eh(s, t)
|
||||
}
|
||||
}
|
||||
|
||||
// guildScheduledEventDeleteEventHandler is an event handler for GuildScheduledEventDelete events.
|
||||
type guildScheduledEventDeleteEventHandler func(*Session, *GuildScheduledEventDelete)
|
||||
|
||||
// Type returns the event type for GuildScheduledEventDelete events.
|
||||
func (eh guildScheduledEventDeleteEventHandler) Type() string {
|
||||
return guildScheduledEventDeleteEventType
|
||||
}
|
||||
|
||||
// New returns a new instance of GuildScheduledEventDelete.
|
||||
func (eh guildScheduledEventDeleteEventHandler) New() interface{} {
|
||||
return &GuildScheduledEventDelete{}
|
||||
}
|
||||
|
||||
// Handle is the handler for GuildScheduledEventDelete events.
|
||||
func (eh guildScheduledEventDeleteEventHandler) Handle(s *Session, i interface{}) {
|
||||
if t, ok := i.(*GuildScheduledEventDelete); ok {
|
||||
eh(s, t)
|
||||
}
|
||||
}
|
||||
|
||||
// guildMemberAddEventHandler is an event handler for GuildMemberAdd events.
|
||||
type guildMemberAddEventHandler func(*Session, *GuildMemberAdd)
|
||||
|
||||
@@ -458,6 +530,66 @@ func (eh guildUpdateEventHandler) Handle(s *Session, i interface{}) {
|
||||
}
|
||||
}
|
||||
|
||||
// interactionCreateEventHandler is an event handler for InteractionCreate events.
|
||||
type interactionCreateEventHandler func(*Session, *InteractionCreate)
|
||||
|
||||
// Type returns the event type for InteractionCreate events.
|
||||
func (eh interactionCreateEventHandler) Type() string {
|
||||
return interactionCreateEventType
|
||||
}
|
||||
|
||||
// New returns a new instance of InteractionCreate.
|
||||
func (eh interactionCreateEventHandler) New() interface{} {
|
||||
return &InteractionCreate{}
|
||||
}
|
||||
|
||||
// Handle is the handler for InteractionCreate events.
|
||||
func (eh interactionCreateEventHandler) Handle(s *Session, i interface{}) {
|
||||
if t, ok := i.(*InteractionCreate); ok {
|
||||
eh(s, t)
|
||||
}
|
||||
}
|
||||
|
||||
// inviteCreateEventHandler is an event handler for InviteCreate events.
|
||||
type inviteCreateEventHandler func(*Session, *InviteCreate)
|
||||
|
||||
// Type returns the event type for InviteCreate events.
|
||||
func (eh inviteCreateEventHandler) Type() string {
|
||||
return inviteCreateEventType
|
||||
}
|
||||
|
||||
// New returns a new instance of InviteCreate.
|
||||
func (eh inviteCreateEventHandler) New() interface{} {
|
||||
return &InviteCreate{}
|
||||
}
|
||||
|
||||
// Handle is the handler for InviteCreate events.
|
||||
func (eh inviteCreateEventHandler) Handle(s *Session, i interface{}) {
|
||||
if t, ok := i.(*InviteCreate); ok {
|
||||
eh(s, t)
|
||||
}
|
||||
}
|
||||
|
||||
// inviteDeleteEventHandler is an event handler for InviteDelete events.
|
||||
type inviteDeleteEventHandler func(*Session, *InviteDelete)
|
||||
|
||||
// Type returns the event type for InviteDelete events.
|
||||
func (eh inviteDeleteEventHandler) Type() string {
|
||||
return inviteDeleteEventType
|
||||
}
|
||||
|
||||
// New returns a new instance of InviteDelete.
|
||||
func (eh inviteDeleteEventHandler) New() interface{} {
|
||||
return &InviteDelete{}
|
||||
}
|
||||
|
||||
// Handle is the handler for InviteDelete events.
|
||||
func (eh inviteDeleteEventHandler) Handle(s *Session, i interface{}) {
|
||||
if t, ok := i.(*InviteDelete); ok {
|
||||
eh(s, t)
|
||||
}
|
||||
}
|
||||
|
||||
// messageAckEventHandler is an event handler for MessageAck events.
|
||||
type messageAckEventHandler func(*Session, *MessageAck)
|
||||
|
||||
@@ -753,6 +885,126 @@ func (eh resumedEventHandler) Handle(s *Session, i interface{}) {
|
||||
}
|
||||
}
|
||||
|
||||
// threadCreateEventHandler is an event handler for ThreadCreate events.
|
||||
type threadCreateEventHandler func(*Session, *ThreadCreate)
|
||||
|
||||
// Type returns the event type for ThreadCreate events.
|
||||
func (eh threadCreateEventHandler) Type() string {
|
||||
return threadCreateEventType
|
||||
}
|
||||
|
||||
// New returns a new instance of ThreadCreate.
|
||||
func (eh threadCreateEventHandler) New() interface{} {
|
||||
return &ThreadCreate{}
|
||||
}
|
||||
|
||||
// Handle is the handler for ThreadCreate events.
|
||||
func (eh threadCreateEventHandler) Handle(s *Session, i interface{}) {
|
||||
if t, ok := i.(*ThreadCreate); ok {
|
||||
eh(s, t)
|
||||
}
|
||||
}
|
||||
|
||||
// threadDeleteEventHandler is an event handler for ThreadDelete events.
|
||||
type threadDeleteEventHandler func(*Session, *ThreadDelete)
|
||||
|
||||
// Type returns the event type for ThreadDelete events.
|
||||
func (eh threadDeleteEventHandler) Type() string {
|
||||
return threadDeleteEventType
|
||||
}
|
||||
|
||||
// New returns a new instance of ThreadDelete.
|
||||
func (eh threadDeleteEventHandler) New() interface{} {
|
||||
return &ThreadDelete{}
|
||||
}
|
||||
|
||||
// Handle is the handler for ThreadDelete events.
|
||||
func (eh threadDeleteEventHandler) Handle(s *Session, i interface{}) {
|
||||
if t, ok := i.(*ThreadDelete); ok {
|
||||
eh(s, t)
|
||||
}
|
||||
}
|
||||
|
||||
// threadListSyncEventHandler is an event handler for ThreadListSync events.
|
||||
type threadListSyncEventHandler func(*Session, *ThreadListSync)
|
||||
|
||||
// Type returns the event type for ThreadListSync events.
|
||||
func (eh threadListSyncEventHandler) Type() string {
|
||||
return threadListSyncEventType
|
||||
}
|
||||
|
||||
// New returns a new instance of ThreadListSync.
|
||||
func (eh threadListSyncEventHandler) New() interface{} {
|
||||
return &ThreadListSync{}
|
||||
}
|
||||
|
||||
// Handle is the handler for ThreadListSync events.
|
||||
func (eh threadListSyncEventHandler) Handle(s *Session, i interface{}) {
|
||||
if t, ok := i.(*ThreadListSync); ok {
|
||||
eh(s, t)
|
||||
}
|
||||
}
|
||||
|
||||
// threadMemberUpdateEventHandler is an event handler for ThreadMemberUpdate events.
|
||||
type threadMemberUpdateEventHandler func(*Session, *ThreadMemberUpdate)
|
||||
|
||||
// Type returns the event type for ThreadMemberUpdate events.
|
||||
func (eh threadMemberUpdateEventHandler) Type() string {
|
||||
return threadMemberUpdateEventType
|
||||
}
|
||||
|
||||
// New returns a new instance of ThreadMemberUpdate.
|
||||
func (eh threadMemberUpdateEventHandler) New() interface{} {
|
||||
return &ThreadMemberUpdate{}
|
||||
}
|
||||
|
||||
// Handle is the handler for ThreadMemberUpdate events.
|
||||
func (eh threadMemberUpdateEventHandler) Handle(s *Session, i interface{}) {
|
||||
if t, ok := i.(*ThreadMemberUpdate); ok {
|
||||
eh(s, t)
|
||||
}
|
||||
}
|
||||
|
||||
// threadMembersUpdateEventHandler is an event handler for ThreadMembersUpdate events.
|
||||
type threadMembersUpdateEventHandler func(*Session, *ThreadMembersUpdate)
|
||||
|
||||
// Type returns the event type for ThreadMembersUpdate events.
|
||||
func (eh threadMembersUpdateEventHandler) Type() string {
|
||||
return threadMembersUpdateEventType
|
||||
}
|
||||
|
||||
// New returns a new instance of ThreadMembersUpdate.
|
||||
func (eh threadMembersUpdateEventHandler) New() interface{} {
|
||||
return &ThreadMembersUpdate{}
|
||||
}
|
||||
|
||||
// Handle is the handler for ThreadMembersUpdate events.
|
||||
func (eh threadMembersUpdateEventHandler) Handle(s *Session, i interface{}) {
|
||||
if t, ok := i.(*ThreadMembersUpdate); ok {
|
||||
eh(s, t)
|
||||
}
|
||||
}
|
||||
|
||||
// threadUpdateEventHandler is an event handler for ThreadUpdate events.
|
||||
type threadUpdateEventHandler func(*Session, *ThreadUpdate)
|
||||
|
||||
// Type returns the event type for ThreadUpdate events.
|
||||
func (eh threadUpdateEventHandler) Type() string {
|
||||
return threadUpdateEventType
|
||||
}
|
||||
|
||||
// New returns a new instance of ThreadUpdate.
|
||||
func (eh threadUpdateEventHandler) New() interface{} {
|
||||
return &ThreadUpdate{}
|
||||
}
|
||||
|
||||
// Handle is the handler for ThreadUpdate events.
|
||||
func (eh threadUpdateEventHandler) Handle(s *Session, i interface{}) {
|
||||
if t, ok := i.(*ThreadUpdate); ok {
|
||||
eh(s, t)
|
||||
}
|
||||
}
|
||||
|
||||
// typingStartEventHandler is an event handler for TypingStart events.
|
||||
type typingStartEventHandler func(*Session, *TypingStart)
|
||||
|
||||
@@ -943,6 +1195,12 @@ func handlerForInterface(handler interface{}) EventHandler {
|
||||
return guildEmojisUpdateEventHandler(v)
|
||||
case func(*Session, *GuildIntegrationsUpdate):
|
||||
return guildIntegrationsUpdateEventHandler(v)
|
||||
case func(*Session, *GuildScheduledEventCreate):
|
||||
return guildScheduledEventCreateEventHandler(v)
|
||||
case func(*Session, *GuildScheduledEventUpdate):
|
||||
return guildScheduledEventUpdateEventHandler(v)
|
||||
case func(*Session, *GuildScheduledEventDelete):
|
||||
return guildScheduledEventDeleteEventHandler(v)
|
||||
case func(*Session, *GuildMemberAdd):
|
||||
return guildMemberAddEventHandler(v)
|
||||
case func(*Session, *GuildMemberRemove):
|
||||
@@ -959,6 +1217,12 @@ func handlerForInterface(handler interface{}) EventHandler {
|
||||
return guildRoleUpdateEventHandler(v)
|
||||
case func(*Session, *GuildUpdate):
|
||||
return guildUpdateEventHandler(v)
|
||||
case func(*Session, *InteractionCreate):
|
||||
return interactionCreateEventHandler(v)
|
||||
case func(*Session, *InviteCreate):
|
||||
return inviteCreateEventHandler(v)
|
||||
case func(*Session, *InviteDelete):
|
||||
return inviteDeleteEventHandler(v)
|
||||
case func(*Session, *MessageAck):
|
||||
return messageAckEventHandler(v)
|
||||
case func(*Session, *MessageCreate):
|
||||
@@ -989,6 +1253,18 @@ func handlerForInterface(handler interface{}) EventHandler {
|
||||
return relationshipRemoveEventHandler(v)
|
||||
case func(*Session, *Resumed):
|
||||
return resumedEventHandler(v)
|
||||
case func(*Session, *ThreadCreate):
|
||||
return threadCreateEventHandler(v)
|
||||
case func(*Session, *ThreadDelete):
|
||||
return threadDeleteEventHandler(v)
|
||||
case func(*Session, *ThreadListSync):
|
||||
return threadListSyncEventHandler(v)
|
||||
case func(*Session, *ThreadMemberUpdate):
|
||||
return threadMemberUpdateEventHandler(v)
|
||||
case func(*Session, *ThreadMembersUpdate):
|
||||
return threadMembersUpdateEventHandler(v)
|
||||
case func(*Session, *ThreadUpdate):
|
||||
return threadUpdateEventHandler(v)
|
||||
case func(*Session, *TypingStart):
|
||||
return typingStartEventHandler(v)
|
||||
case func(*Session, *UserGuildSettingsUpdate):
|
||||
@@ -1021,6 +1297,9 @@ func init() {
|
||||
registerInterfaceProvider(guildDeleteEventHandler(nil))
|
||||
registerInterfaceProvider(guildEmojisUpdateEventHandler(nil))
|
||||
registerInterfaceProvider(guildIntegrationsUpdateEventHandler(nil))
|
||||
registerInterfaceProvider(guildScheduledEventCreateEventHandler(nil))
|
||||
registerInterfaceProvider(guildScheduledEventUpdateEventHandler(nil))
|
||||
registerInterfaceProvider(guildScheduledEventDeleteEventHandler(nil))
|
||||
registerInterfaceProvider(guildMemberAddEventHandler(nil))
|
||||
registerInterfaceProvider(guildMemberRemoveEventHandler(nil))
|
||||
registerInterfaceProvider(guildMemberUpdateEventHandler(nil))
|
||||
@@ -1029,6 +1308,9 @@ func init() {
|
||||
registerInterfaceProvider(guildRoleDeleteEventHandler(nil))
|
||||
registerInterfaceProvider(guildRoleUpdateEventHandler(nil))
|
||||
registerInterfaceProvider(guildUpdateEventHandler(nil))
|
||||
registerInterfaceProvider(interactionCreateEventHandler(nil))
|
||||
registerInterfaceProvider(inviteCreateEventHandler(nil))
|
||||
registerInterfaceProvider(inviteDeleteEventHandler(nil))
|
||||
registerInterfaceProvider(messageAckEventHandler(nil))
|
||||
registerInterfaceProvider(messageCreateEventHandler(nil))
|
||||
registerInterfaceProvider(messageDeleteEventHandler(nil))
|
||||
@@ -1043,6 +1325,12 @@ func init() {
|
||||
registerInterfaceProvider(relationshipAddEventHandler(nil))
|
||||
registerInterfaceProvider(relationshipRemoveEventHandler(nil))
|
||||
registerInterfaceProvider(resumedEventHandler(nil))
|
||||
registerInterfaceProvider(threadCreateEventHandler(nil))
|
||||
registerInterfaceProvider(threadDeleteEventHandler(nil))
|
||||
registerInterfaceProvider(threadListSyncEventHandler(nil))
|
||||
registerInterfaceProvider(threadMemberUpdateEventHandler(nil))
|
||||
registerInterfaceProvider(threadMembersUpdateEventHandler(nil))
|
||||
registerInterfaceProvider(threadUpdateEventHandler(nil))
|
||||
registerInterfaceProvider(typingStartEventHandler(nil))
|
||||
registerInterfaceProvider(userGuildSettingsUpdateEventHandler(nil))
|
||||
registerInterfaceProvider(userNoteUpdateEventHandler(nil))
|
||||
@@ -73,6 +73,53 @@ type ChannelPinsUpdate struct {
|
||||
GuildID string `json:"guild_id,omitempty"`
|
||||
}
|
||||
|
||||
// ThreadCreate is the data for a ThreadCreate event.
|
||||
type ThreadCreate struct {
|
||||
*Channel
|
||||
NewlyCreated bool `json:"newly_created"`
|
||||
}
|
||||
|
||||
// ThreadUpdate is the data for a ThreadUpdate event.
|
||||
type ThreadUpdate struct {
|
||||
*Channel
|
||||
BeforeUpdate *Channel `json:"-"`
|
||||
}
|
||||
|
||||
// ThreadDelete is the data for a ThreadDelete event.
|
||||
type ThreadDelete struct {
|
||||
*Channel
|
||||
}
|
||||
|
||||
// ThreadListSync is the data for a ThreadListSync event.
|
||||
type ThreadListSync struct {
|
||||
// The id of the guild
|
||||
GuildID string `json:"guild_id"`
|
||||
// The parent channel ids whose threads are being synced.
|
||||
// If omitted, then threads were synced for the entire guild.
|
||||
// This array may contain channel_ids that have no active threads as well, so you know to clear that data.
|
||||
ChannelIDs []string `json:"channel_ids"`
|
||||
// All active threads in the given channels that the current user can access
|
||||
Threads []*Channel `json:"threads"`
|
||||
// All thread member objects from the synced threads for the current user,
|
||||
// indicating which threads the current user has been added to
|
||||
Members []*ThreadMember `json:"members"`
|
||||
}
|
||||
|
||||
// ThreadMemberUpdate is the data for a ThreadMemberUpdate event.
|
||||
type ThreadMemberUpdate struct {
|
||||
*ThreadMember
|
||||
GuildID string `json:"guild_id"`
|
||||
}
|
||||
|
||||
// ThreadMembersUpdate is the data for a ThreadMembersUpdate event.
|
||||
type ThreadMembersUpdate struct {
|
||||
ID string `json:"id"`
|
||||
GuildID string `json:"guild_id"`
|
||||
MemberCount int `json:"member_count"`
|
||||
AddedMembers []AddedThreadMember `json:"added_members"`
|
||||
RemovedMembers []string `json:"removed_member_ids"`
|
||||
}
|
||||
|
||||
// GuildCreate is the data for a GuildCreate event.
|
||||
type GuildCreate struct {
|
||||
*Guild
|
||||
@@ -86,6 +133,7 @@ type GuildUpdate struct {
|
||||
// GuildDelete is the data for a GuildDelete event.
|
||||
type GuildDelete struct {
|
||||
*Guild
|
||||
BeforeDelete *Guild `json:"-"`
|
||||
}
|
||||
|
||||
// GuildBanAdd is the data for a GuildBanAdd event.
|
||||
@@ -151,6 +199,21 @@ type GuildIntegrationsUpdate struct {
|
||||
GuildID string `json:"guild_id"`
|
||||
}
|
||||
|
||||
// GuildScheduledEventCreate is the data for a GuildScheduledEventCreate event.
|
||||
type GuildScheduledEventCreate struct {
|
||||
*GuildScheduledEvent
|
||||
}
|
||||
|
||||
// GuildScheduledEventUpdate is the data for a GuildScheduledEventUpdate event.
|
||||
type GuildScheduledEventUpdate struct {
|
||||
*GuildScheduledEvent
|
||||
}
|
||||
|
||||
// GuildScheduledEventDelete is the data for a GuildScheduledEventDelete event.
|
||||
type GuildScheduledEventDelete struct {
|
||||
*GuildScheduledEvent
|
||||
}
|
||||
|
||||
// MessageAck is the data for a MessageAck event.
|
||||
type MessageAck struct {
|
||||
MessageID string `json:"message_id"`
|
||||
@@ -162,6 +225,11 @@ type MessageCreate struct {
|
||||
*Message
|
||||
}
|
||||
|
||||
// UnmarshalJSON is a helper function to unmarshal MessageCreate object.
|
||||
func (m *MessageCreate) UnmarshalJSON(b []byte) error {
|
||||
return json.Unmarshal(b, &m.Message)
|
||||
}
|
||||
|
||||
// MessageUpdate is the data for a MessageUpdate event.
|
||||
type MessageUpdate struct {
|
||||
*Message
|
||||
@@ -169,15 +237,26 @@ type MessageUpdate struct {
|
||||
BeforeUpdate *Message `json:"-"`
|
||||
}
|
||||
|
||||
// UnmarshalJSON is a helper function to unmarshal MessageUpdate object.
|
||||
func (m *MessageUpdate) UnmarshalJSON(b []byte) error {
|
||||
return json.Unmarshal(b, &m.Message)
|
||||
}
|
||||
|
||||
// MessageDelete is the data for a MessageDelete event.
|
||||
type MessageDelete struct {
|
||||
*Message
|
||||
BeforeDelete *Message `json:"-"`
|
||||
}
|
||||
|
||||
// UnmarshalJSON is a helper function to unmarshal MessageDelete object.
|
||||
func (m *MessageDelete) UnmarshalJSON(b []byte) error {
|
||||
return json.Unmarshal(b, &m.Message)
|
||||
}
|
||||
|
||||
// MessageReactionAdd is the data for a MessageReactionAdd event.
|
||||
type MessageReactionAdd struct {
|
||||
*MessageReaction
|
||||
Member *Member `json:"member,omitempty"`
|
||||
}
|
||||
|
||||
// MessageReactionRemove is the data for a MessageReactionRemove event.
|
||||
@@ -267,3 +346,27 @@ type WebhooksUpdate struct {
|
||||
GuildID string `json:"guild_id"`
|
||||
ChannelID string `json:"channel_id"`
|
||||
}
|
||||
|
||||
// InteractionCreate is the data for a InteractionCreate event
|
||||
type InteractionCreate struct {
|
||||
*Interaction
|
||||
}
|
||||
|
||||
// UnmarshalJSON is a helper function to unmarshal Interaction object.
|
||||
func (i *InteractionCreate) UnmarshalJSON(b []byte) error {
|
||||
return json.Unmarshal(b, &i.Interaction)
|
||||
}
|
||||
|
||||
// InviteCreate is the data for a InviteCreate event
|
||||
type InviteCreate struct {
|
||||
*Invite
|
||||
ChannelID string `json:"channel_id"`
|
||||
GuildID string `json:"guild_id"`
|
||||
}
|
||||
|
||||
// InviteDelete is the data for a InviteDelete event
|
||||
type InviteDelete struct {
|
||||
ChannelID string `json:"channel_id"`
|
||||
GuildID string `json:"guild_id"`
|
||||
Code string `json:"code"`
|
||||
}
|
||||
568
vendor/github.com/bwmarrin/discordgo/interactions.go
generated
vendored
Normal file
568
vendor/github.com/bwmarrin/discordgo/interactions.go
generated
vendored
Normal file
@@ -0,0 +1,568 @@
|
||||
package discordgo
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/ed25519"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
// InteractionDeadline is the time allowed to respond to an interaction.
|
||||
const InteractionDeadline = time.Second * 3
|
||||
|
||||
// ApplicationCommandType represents the type of application command.
|
||||
type ApplicationCommandType uint8
|
||||
|
||||
// Application command types
|
||||
const (
|
||||
// ChatApplicationCommand is default command type. They are slash commands (i.e. called directly from the chat).
|
||||
ChatApplicationCommand ApplicationCommandType = 1
|
||||
// UserApplicationCommand adds command to user context menu.
|
||||
UserApplicationCommand ApplicationCommandType = 2
|
||||
// MessageApplicationCommand adds command to message context menu.
|
||||
MessageApplicationCommand ApplicationCommandType = 3
|
||||
)
|
||||
|
||||
// ApplicationCommand represents an application's slash command.
|
||||
type ApplicationCommand struct {
|
||||
ID string `json:"id,omitempty"`
|
||||
ApplicationID string `json:"application_id,omitempty"`
|
||||
Version string `json:"version,omitempty"`
|
||||
Type ApplicationCommandType `json:"type,omitempty"`
|
||||
Name string `json:"name"`
|
||||
DefaultPermission *bool `json:"default_permission,omitempty"`
|
||||
|
||||
// NOTE: Chat commands only. Otherwise it mustn't be set.
|
||||
|
||||
Description string `json:"description,omitempty"`
|
||||
Options []*ApplicationCommandOption `json:"options"`
|
||||
}
|
||||
|
||||
// ApplicationCommandOptionType indicates the type of a slash command's option.
|
||||
type ApplicationCommandOptionType uint8
|
||||
|
||||
// Application command option types.
|
||||
const (
|
||||
ApplicationCommandOptionSubCommand ApplicationCommandOptionType = 1
|
||||
ApplicationCommandOptionSubCommandGroup ApplicationCommandOptionType = 2
|
||||
ApplicationCommandOptionString ApplicationCommandOptionType = 3
|
||||
ApplicationCommandOptionInteger ApplicationCommandOptionType = 4
|
||||
ApplicationCommandOptionBoolean ApplicationCommandOptionType = 5
|
||||
ApplicationCommandOptionUser ApplicationCommandOptionType = 6
|
||||
ApplicationCommandOptionChannel ApplicationCommandOptionType = 7
|
||||
ApplicationCommandOptionRole ApplicationCommandOptionType = 8
|
||||
ApplicationCommandOptionMentionable ApplicationCommandOptionType = 9
|
||||
ApplicationCommandOptionNumber ApplicationCommandOptionType = 10
|
||||
ApplicationCommandOptionAttachment ApplicationCommandOptionType = 11
|
||||
)
|
||||
|
||||
func (t ApplicationCommandOptionType) String() string {
|
||||
switch t {
|
||||
case ApplicationCommandOptionSubCommand:
|
||||
return "SubCommand"
|
||||
case ApplicationCommandOptionSubCommandGroup:
|
||||
return "SubCommandGroup"
|
||||
case ApplicationCommandOptionString:
|
||||
return "String"
|
||||
case ApplicationCommandOptionInteger:
|
||||
return "Integer"
|
||||
case ApplicationCommandOptionBoolean:
|
||||
return "Boolean"
|
||||
case ApplicationCommandOptionUser:
|
||||
return "User"
|
||||
case ApplicationCommandOptionChannel:
|
||||
return "Channel"
|
||||
case ApplicationCommandOptionRole:
|
||||
return "Role"
|
||||
case ApplicationCommandOptionMentionable:
|
||||
return "Mentionable"
|
||||
case ApplicationCommandOptionNumber:
|
||||
return "Number"
|
||||
case ApplicationCommandOptionAttachment:
|
||||
return "Attachment"
|
||||
}
|
||||
return fmt.Sprintf("ApplicationCommandOptionType(%d)", t)
|
||||
}
|
||||
|
||||
// ApplicationCommandOption represents an option/subcommand/subcommands group.
|
||||
type ApplicationCommandOption struct {
|
||||
Type ApplicationCommandOptionType `json:"type"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description,omitempty"`
|
||||
// NOTE: This feature was on the API, but at some point developers decided to remove it.
|
||||
// So I commented it, until it will be officially on the docs.
|
||||
// Default bool `json:"default"`
|
||||
|
||||
ChannelTypes []ChannelType `json:"channel_types"`
|
||||
Required bool `json:"required"`
|
||||
Options []*ApplicationCommandOption `json:"options"`
|
||||
|
||||
// NOTE: mutually exclusive with Choices.
|
||||
Autocomplete bool `json:"autocomplete"`
|
||||
Choices []*ApplicationCommandOptionChoice `json:"choices"`
|
||||
// Minimal value of number/integer option.
|
||||
MinValue *float64 `json:"min_value,omitempty"`
|
||||
// Maximum value of number/integer option.
|
||||
MaxValue float64 `json:"max_value,omitempty"`
|
||||
}
|
||||
|
||||
// ApplicationCommandOptionChoice represents a slash command option choice.
|
||||
type ApplicationCommandOptionChoice struct {
|
||||
Name string `json:"name"`
|
||||
Value interface{} `json:"value"`
|
||||
}
|
||||
|
||||
// ApplicationCommandPermissions represents a single user or role permission for a command.
|
||||
type ApplicationCommandPermissions struct {
|
||||
ID string `json:"id"`
|
||||
Type ApplicationCommandPermissionType `json:"type"`
|
||||
Permission bool `json:"permission"`
|
||||
}
|
||||
|
||||
// ApplicationCommandPermissionsList represents a list of ApplicationCommandPermissions, needed for serializing to JSON.
|
||||
type ApplicationCommandPermissionsList struct {
|
||||
Permissions []*ApplicationCommandPermissions `json:"permissions"`
|
||||
}
|
||||
|
||||
// GuildApplicationCommandPermissions represents all permissions for a single guild command.
|
||||
type GuildApplicationCommandPermissions struct {
|
||||
ID string `json:"id"`
|
||||
ApplicationID string `json:"application_id"`
|
||||
GuildID string `json:"guild_id"`
|
||||
Permissions []*ApplicationCommandPermissions `json:"permissions"`
|
||||
}
|
||||
|
||||
// ApplicationCommandPermissionType indicates whether a permission is user or role based.
|
||||
type ApplicationCommandPermissionType uint8
|
||||
|
||||
// Application command permission types.
|
||||
const (
|
||||
ApplicationCommandPermissionTypeRole ApplicationCommandPermissionType = 1
|
||||
ApplicationCommandPermissionTypeUser ApplicationCommandPermissionType = 2
|
||||
)
|
||||
|
||||
// InteractionType indicates the type of an interaction event.
|
||||
type InteractionType uint8
|
||||
|
||||
// Interaction types
|
||||
const (
|
||||
InteractionPing InteractionType = 1
|
||||
InteractionApplicationCommand InteractionType = 2
|
||||
InteractionMessageComponent InteractionType = 3
|
||||
InteractionApplicationCommandAutocomplete InteractionType = 4
|
||||
InteractionModalSubmit InteractionType = 5
|
||||
)
|
||||
|
||||
func (t InteractionType) String() string {
|
||||
switch t {
|
||||
case InteractionPing:
|
||||
return "Ping"
|
||||
case InteractionApplicationCommand:
|
||||
return "ApplicationCommand"
|
||||
case InteractionMessageComponent:
|
||||
return "MessageComponent"
|
||||
case InteractionModalSubmit:
|
||||
return "ModalSubmit"
|
||||
}
|
||||
return fmt.Sprintf("InteractionType(%d)", t)
|
||||
}
|
||||
|
||||
// Interaction represents data of an interaction.
|
||||
type Interaction struct {
|
||||
ID string `json:"id"`
|
||||
Type InteractionType `json:"type"`
|
||||
Data InteractionData `json:"data"`
|
||||
GuildID string `json:"guild_id"`
|
||||
ChannelID string `json:"channel_id"`
|
||||
|
||||
// The message on which interaction was used.
|
||||
// NOTE: this field is only filled when a button click triggered the interaction. Otherwise it will be nil.
|
||||
Message *Message `json:"message"`
|
||||
|
||||
// The member who invoked this interaction.
|
||||
// NOTE: this field is only filled when the slash command was invoked in a guild;
|
||||
// if it was invoked in a DM, the `User` field will be filled instead.
|
||||
// Make sure to check for `nil` before using this field.
|
||||
Member *Member `json:"member"`
|
||||
// The user who invoked this interaction.
|
||||
// NOTE: this field is only filled when the slash command was invoked in a DM;
|
||||
// if it was invoked in a guild, the `Member` field will be filled instead.
|
||||
// Make sure to check for `nil` before using this field.
|
||||
User *User `json:"user"`
|
||||
|
||||
// The user's discord client locale.
|
||||
Locale Locale `json:"locale"`
|
||||
// The guild's locale. This defaults to EnglishUS
|
||||
// NOTE: this field is only filled when the interaction was invoked in a guild.
|
||||
GuildLocale *Locale `json:"guild_locale"`
|
||||
|
||||
Token string `json:"token"`
|
||||
Version int `json:"version"`
|
||||
}
|
||||
|
||||
type interaction Interaction
|
||||
|
||||
type rawInteraction struct {
|
||||
interaction
|
||||
Data json.RawMessage `json:"data"`
|
||||
}
|
||||
|
||||
// UnmarshalJSON is a method for unmarshalling JSON object to Interaction.
|
||||
func (i *Interaction) UnmarshalJSON(raw []byte) error {
|
||||
var tmp rawInteraction
|
||||
err := json.Unmarshal(raw, &tmp)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*i = Interaction(tmp.interaction)
|
||||
|
||||
switch tmp.Type {
|
||||
case InteractionApplicationCommand, InteractionApplicationCommandAutocomplete:
|
||||
v := ApplicationCommandInteractionData{}
|
||||
err = json.Unmarshal(tmp.Data, &v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
i.Data = v
|
||||
case InteractionMessageComponent:
|
||||
v := MessageComponentInteractionData{}
|
||||
err = json.Unmarshal(tmp.Data, &v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
i.Data = v
|
||||
case InteractionModalSubmit:
|
||||
v := ModalSubmitInteractionData{}
|
||||
err = json.Unmarshal(tmp.Data, &v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
i.Data = v
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// MessageComponentData is helper function to assert the inner InteractionData to MessageComponentInteractionData.
|
||||
// Make sure to check that the Type of the interaction is InteractionMessageComponent before calling.
|
||||
func (i Interaction) MessageComponentData() (data MessageComponentInteractionData) {
|
||||
if i.Type != InteractionMessageComponent {
|
||||
panic("MessageComponentData called on interaction of type " + i.Type.String())
|
||||
}
|
||||
return i.Data.(MessageComponentInteractionData)
|
||||
}
|
||||
|
||||
// ApplicationCommandData is helper function to assert the inner InteractionData to ApplicationCommandInteractionData.
|
||||
// Make sure to check that the Type of the interaction is InteractionApplicationCommand before calling.
|
||||
func (i Interaction) ApplicationCommandData() (data ApplicationCommandInteractionData) {
|
||||
if i.Type != InteractionApplicationCommand && i.Type != InteractionApplicationCommandAutocomplete {
|
||||
panic("ApplicationCommandData called on interaction of type " + i.Type.String())
|
||||
}
|
||||
return i.Data.(ApplicationCommandInteractionData)
|
||||
}
|
||||
|
||||
// ModalSubmitData is helper function to assert the inner InteractionData to ModalSubmitInteractionData.
|
||||
// Make sure to check that the Type of the interaction is InteractionModalSubmit before calling.
|
||||
func (i Interaction) ModalSubmitData() (data ModalSubmitInteractionData) {
|
||||
if i.Type != InteractionModalSubmit {
|
||||
panic("ModalSubmitData called on interaction of type " + i.Type.String())
|
||||
}
|
||||
return i.Data.(ModalSubmitInteractionData)
|
||||
}
|
||||
|
||||
// InteractionData is a common interface for all types of interaction data.
|
||||
type InteractionData interface {
|
||||
Type() InteractionType
|
||||
}
|
||||
|
||||
// ApplicationCommandInteractionData contains the data of application command interaction.
|
||||
type ApplicationCommandInteractionData struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Resolved *ApplicationCommandInteractionDataResolved `json:"resolved"`
|
||||
|
||||
// Slash command options
|
||||
Options []*ApplicationCommandInteractionDataOption `json:"options"`
|
||||
// Target (user/message) id on which context menu command was called.
|
||||
// The details are stored in Resolved according to command type.
|
||||
TargetID string `json:"target_id"`
|
||||
}
|
||||
|
||||
// ApplicationCommandInteractionDataResolved contains resolved data of command execution.
|
||||
// Partial Member objects are missing user, deaf and mute fields.
|
||||
// Partial Channel objects only have id, name, type and permissions fields.
|
||||
type ApplicationCommandInteractionDataResolved 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"`
|
||||
Messages map[string]*Message `json:"messages"`
|
||||
Attachments map[string]*MessageAttachment `json:"attachments"`
|
||||
}
|
||||
|
||||
// Type returns the type of interaction data.
|
||||
func (ApplicationCommandInteractionData) Type() InteractionType {
|
||||
return InteractionApplicationCommand
|
||||
}
|
||||
|
||||
// MessageComponentInteractionData contains the data of message component interaction.
|
||||
type MessageComponentInteractionData struct {
|
||||
CustomID string `json:"custom_id"`
|
||||
ComponentType ComponentType `json:"component_type"`
|
||||
|
||||
// NOTE: Only filled when ComponentType is SelectMenuComponent (3). Otherwise is nil.
|
||||
Values []string `json:"values"`
|
||||
}
|
||||
|
||||
// Type returns the type of interaction data.
|
||||
func (MessageComponentInteractionData) Type() InteractionType {
|
||||
return InteractionMessageComponent
|
||||
}
|
||||
|
||||
// ModalSubmitInteractionData contains the data of modal submit interaction.
|
||||
type ModalSubmitInteractionData struct {
|
||||
CustomID string `json:"custom_id"`
|
||||
Components []MessageComponent `json:"-"`
|
||||
}
|
||||
|
||||
// Type returns the type of interaction data.
|
||||
func (ModalSubmitInteractionData) Type() InteractionType {
|
||||
return InteractionModalSubmit
|
||||
}
|
||||
|
||||
// UnmarshalJSON is a helper function to correctly unmarshal Components.
|
||||
func (d *ModalSubmitInteractionData) UnmarshalJSON(data []byte) error {
|
||||
type modalSubmitInteractionData ModalSubmitInteractionData
|
||||
var v struct {
|
||||
modalSubmitInteractionData
|
||||
RawComponents []unmarshalableMessageComponent `json:"components"`
|
||||
}
|
||||
err := json.Unmarshal(data, &v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*d = ModalSubmitInteractionData(v.modalSubmitInteractionData)
|
||||
d.Components = make([]MessageComponent, len(v.RawComponents))
|
||||
for i, v := range v.RawComponents {
|
||||
d.Components[i] = v.MessageComponent
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// ApplicationCommandInteractionDataOption represents an option of a slash command.
|
||||
type ApplicationCommandInteractionDataOption struct {
|
||||
Name string `json:"name"`
|
||||
Type ApplicationCommandOptionType `json:"type"`
|
||||
// NOTE: Contains the value specified by Type.
|
||||
Value interface{} `json:"value,omitempty"`
|
||||
Options []*ApplicationCommandInteractionDataOption `json:"options,omitempty"`
|
||||
|
||||
// NOTE: autocomplete interaction only.
|
||||
Focused bool `json:"focused,omitempty"`
|
||||
}
|
||||
|
||||
// IntValue is a utility function for casting option value to integer
|
||||
func (o ApplicationCommandInteractionDataOption) IntValue() int64 {
|
||||
if o.Type != ApplicationCommandOptionInteger {
|
||||
panic("IntValue called on data option of type " + o.Type.String())
|
||||
}
|
||||
return int64(o.Value.(float64))
|
||||
}
|
||||
|
||||
// UintValue is a utility function for casting option value to unsigned integer
|
||||
func (o ApplicationCommandInteractionDataOption) UintValue() uint64 {
|
||||
if o.Type != ApplicationCommandOptionInteger {
|
||||
panic("UintValue called on data option of type " + o.Type.String())
|
||||
}
|
||||
return uint64(o.Value.(float64))
|
||||
}
|
||||
|
||||
// FloatValue is a utility function for casting option value to float
|
||||
func (o ApplicationCommandInteractionDataOption) FloatValue() float64 {
|
||||
if o.Type != ApplicationCommandOptionNumber {
|
||||
panic("FloatValue called on data option of type " + o.Type.String())
|
||||
}
|
||||
return o.Value.(float64)
|
||||
}
|
||||
|
||||
// StringValue is a utility function for casting option value to string
|
||||
func (o ApplicationCommandInteractionDataOption) StringValue() string {
|
||||
if o.Type != ApplicationCommandOptionString {
|
||||
panic("StringValue called on data option of type " + o.Type.String())
|
||||
}
|
||||
return o.Value.(string)
|
||||
}
|
||||
|
||||
// BoolValue is a utility function for casting option value to bool
|
||||
func (o ApplicationCommandInteractionDataOption) BoolValue() bool {
|
||||
if o.Type != ApplicationCommandOptionBoolean {
|
||||
panic("BoolValue called on data option of type " + o.Type.String())
|
||||
}
|
||||
return o.Value.(bool)
|
||||
}
|
||||
|
||||
// ChannelValue is a utility function for casting option value to channel object.
|
||||
// s : Session object, if not nil, function additionally fetches all channel's data
|
||||
func (o ApplicationCommandInteractionDataOption) ChannelValue(s *Session) *Channel {
|
||||
if o.Type != ApplicationCommandOptionChannel {
|
||||
panic("ChannelValue called on data option of type " + o.Type.String())
|
||||
}
|
||||
chanID := o.Value.(string)
|
||||
|
||||
if s == nil {
|
||||
return &Channel{ID: chanID}
|
||||
}
|
||||
|
||||
ch, err := s.State.Channel(chanID)
|
||||
if err != nil {
|
||||
ch, err = s.Channel(chanID)
|
||||
if err != nil {
|
||||
return &Channel{ID: chanID}
|
||||
}
|
||||
}
|
||||
|
||||
return ch
|
||||
}
|
||||
|
||||
// RoleValue is a utility function for casting option value to role object.
|
||||
// s : Session object, if not nil, function additionally fetches all role's data
|
||||
func (o ApplicationCommandInteractionDataOption) RoleValue(s *Session, gID string) *Role {
|
||||
if o.Type != ApplicationCommandOptionRole && o.Type != ApplicationCommandOptionMentionable {
|
||||
panic("RoleValue called on data option of type " + o.Type.String())
|
||||
}
|
||||
roleID := o.Value.(string)
|
||||
|
||||
if s == nil || gID == "" {
|
||||
return &Role{ID: roleID}
|
||||
}
|
||||
|
||||
r, err := s.State.Role(roleID, gID)
|
||||
if err != nil {
|
||||
roles, err := s.GuildRoles(gID)
|
||||
if err == nil {
|
||||
for _, r = range roles {
|
||||
if r.ID == roleID {
|
||||
return r
|
||||
}
|
||||
}
|
||||
}
|
||||
return &Role{ID: roleID}
|
||||
}
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
// UserValue is a utility function for casting option value to user object.
|
||||
// s : Session object, if not nil, function additionally fetches all user's data
|
||||
func (o ApplicationCommandInteractionDataOption) UserValue(s *Session) *User {
|
||||
if o.Type != ApplicationCommandOptionUser && o.Type != ApplicationCommandOptionMentionable {
|
||||
panic("UserValue called on data option of type " + o.Type.String())
|
||||
}
|
||||
userID := o.Value.(string)
|
||||
|
||||
if s == nil {
|
||||
return &User{ID: userID}
|
||||
}
|
||||
|
||||
u, err := s.User(userID)
|
||||
if err != nil {
|
||||
return &User{ID: userID}
|
||||
}
|
||||
|
||||
return u
|
||||
}
|
||||
|
||||
// InteractionResponseType is type of interaction response.
|
||||
type InteractionResponseType uint8
|
||||
|
||||
// Interaction response types.
|
||||
const (
|
||||
// InteractionResponsePong is for ACK ping event.
|
||||
InteractionResponsePong InteractionResponseType = 1
|
||||
// InteractionResponseChannelMessageWithSource is for responding with a message, showing the user's input.
|
||||
InteractionResponseChannelMessageWithSource InteractionResponseType = 4
|
||||
// InteractionResponseDeferredChannelMessageWithSource acknowledges that the event was received, and that a follow-up will come later.
|
||||
InteractionResponseDeferredChannelMessageWithSource InteractionResponseType = 5
|
||||
// InteractionResponseDeferredMessageUpdate acknowledges that the message component interaction event was received, and message will be updated later.
|
||||
InteractionResponseDeferredMessageUpdate InteractionResponseType = 6
|
||||
// InteractionResponseUpdateMessage is for updating the message to which message component was attached.
|
||||
InteractionResponseUpdateMessage InteractionResponseType = 7
|
||||
// InteractionApplicationCommandAutocompleteResult shows autocompletion results. Autocomplete interaction only.
|
||||
InteractionApplicationCommandAutocompleteResult InteractionResponseType = 8
|
||||
// InteractionResponseModal is for responding to an interaction with a modal window.
|
||||
InteractionResponseModal InteractionResponseType = 9
|
||||
)
|
||||
|
||||
// InteractionResponse represents a response for an interaction event.
|
||||
type InteractionResponse struct {
|
||||
Type InteractionResponseType `json:"type,omitempty"`
|
||||
Data *InteractionResponseData `json:"data,omitempty"`
|
||||
}
|
||||
|
||||
// InteractionResponseData is response data for an interaction.
|
||||
type InteractionResponseData struct {
|
||||
TTS bool `json:"tts"`
|
||||
Content string `json:"content"`
|
||||
Components []MessageComponent `json:"components"`
|
||||
Embeds []*MessageEmbed `json:"embeds,omitempty"`
|
||||
AllowedMentions *MessageAllowedMentions `json:"allowed_mentions,omitempty"`
|
||||
Flags uint64 `json:"flags,omitempty"`
|
||||
Files []*File `json:"-"`
|
||||
|
||||
// NOTE: autocomplete interaction only.
|
||||
Choices []*ApplicationCommandOptionChoice `json:"choices,omitempty"`
|
||||
|
||||
// NOTE: modal interaction only.
|
||||
|
||||
CustomID string `json:"custom_id,omitempty"`
|
||||
Title string `json:"title,omitempty"`
|
||||
}
|
||||
|
||||
// VerifyInteraction implements message verification of the discord interactions api
|
||||
// signing algorithm, as documented here:
|
||||
// https://discord.com/developers/docs/interactions/receiving-and-responding#security-and-authorization
|
||||
func VerifyInteraction(r *http.Request, key ed25519.PublicKey) bool {
|
||||
var msg bytes.Buffer
|
||||
|
||||
signature := r.Header.Get("X-Signature-Ed25519")
|
||||
if signature == "" {
|
||||
return false
|
||||
}
|
||||
|
||||
sig, err := hex.DecodeString(signature)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
if len(sig) != ed25519.SignatureSize {
|
||||
return false
|
||||
}
|
||||
|
||||
timestamp := r.Header.Get("X-Signature-Timestamp")
|
||||
if timestamp == "" {
|
||||
return false
|
||||
}
|
||||
|
||||
msg.WriteString(timestamp)
|
||||
|
||||
defer r.Body.Close()
|
||||
var body bytes.Buffer
|
||||
|
||||
// at the end of the function, copy the original body back into the request
|
||||
defer func() {
|
||||
r.Body = ioutil.NopCloser(&body)
|
||||
}()
|
||||
|
||||
// copy body into buffers
|
||||
_, err = io.Copy(&msg, io.TeeReader(r.Body, &body))
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return ed25519.Verify(key, msg.Bytes(), sig)
|
||||
}
|
||||
83
vendor/github.com/bwmarrin/discordgo/locales.go
generated
vendored
Normal file
83
vendor/github.com/bwmarrin/discordgo/locales.go
generated
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
package discordgo
|
||||
|
||||
// Locale represents the accepted languages for Discord.
|
||||
// https://discord.com/developers/docs/reference#locales
|
||||
type Locale string
|
||||
|
||||
// String returns the human-readable string of the locale
|
||||
func (l Locale) String() string {
|
||||
if name, ok := Locales[l]; ok {
|
||||
return name
|
||||
}
|
||||
return Unknown.String()
|
||||
}
|
||||
|
||||
// All defined locales in Discord
|
||||
const (
|
||||
EnglishUS Locale = "en-US"
|
||||
EnglishGB Locale = "en-GB"
|
||||
Bulgarian Locale = "bg"
|
||||
ChineseCN Locale = "zh-CN"
|
||||
ChineseTW Locale = "zh-TW"
|
||||
Croatian Locale = "hr"
|
||||
Czech Locale = "cs"
|
||||
Danish Locale = "da"
|
||||
Dutch Locale = "nl"
|
||||
Finnish Locale = "fi"
|
||||
French Locale = "fr"
|
||||
German Locale = "de"
|
||||
Greek Locale = "el"
|
||||
Hindi Locale = "hi"
|
||||
Hungarian Locale = "hu"
|
||||
Italian Locale = "it"
|
||||
Japanese Locale = "ja"
|
||||
Korean Locale = "ko"
|
||||
Lithuanian Locale = "lt"
|
||||
Norwegian Locale = "no"
|
||||
Polish Locale = "pl"
|
||||
PortugueseBR Locale = "pt-BR"
|
||||
Romanian Locale = "ro"
|
||||
Russian Locale = "ru"
|
||||
SpanishES Locale = "es-ES"
|
||||
Swedish Locale = "sv-SE"
|
||||
Thai Locale = "th"
|
||||
Turkish Locale = "tr"
|
||||
Ukrainian Locale = "uk"
|
||||
Vietnamese Locale = "vi"
|
||||
Unknown Locale = ""
|
||||
)
|
||||
|
||||
// Locales is a map of all the languages codes to their names.
|
||||
var Locales = map[Locale]string{
|
||||
EnglishUS: "English (United States)",
|
||||
EnglishGB: "English (Great Britain)",
|
||||
Bulgarian: "Bulgarian",
|
||||
ChineseCN: "Chinese (China)",
|
||||
ChineseTW: "Chinese (Taiwan)",
|
||||
Croatian: "Croatian",
|
||||
Czech: "Czech",
|
||||
Danish: "Danish",
|
||||
Dutch: "Dutch",
|
||||
Finnish: "Finnish",
|
||||
French: "French",
|
||||
German: "German",
|
||||
Greek: "Greek",
|
||||
Hindi: "Hindi",
|
||||
Hungarian: "Hungarian",
|
||||
Italian: "Italian",
|
||||
Japanese: "Japanese",
|
||||
Korean: "Korean",
|
||||
Lithuanian: "Lithuanian",
|
||||
Norwegian: "Norwegian",
|
||||
Polish: "Polish",
|
||||
PortugueseBR: "Portuguese (Brazil)",
|
||||
Romanian: "Romanian",
|
||||
Russian: "Russian",
|
||||
SpanishES: "Spanish (Spain)",
|
||||
Swedish: "Swedish",
|
||||
Thai: "Thai",
|
||||
Turkish: "Turkish",
|
||||
Ukrainian: "Ukrainian",
|
||||
Vietnamese: "Vietnamese",
|
||||
Unknown: "unknown",
|
||||
}
|
||||
@@ -10,9 +10,11 @@
|
||||
package discordgo
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// MessageType is the type of Message
|
||||
@@ -21,23 +23,26 @@ type MessageType int
|
||||
|
||||
// Block contains the valid known MessageType values
|
||||
const (
|
||||
MessageTypeDefault MessageType = iota
|
||||
MessageTypeRecipientAdd
|
||||
MessageTypeRecipientRemove
|
||||
MessageTypeCall
|
||||
MessageTypeChannelNameChange
|
||||
MessageTypeChannelIconChange
|
||||
MessageTypeChannelPinnedMessage
|
||||
MessageTypeGuildMemberJoin
|
||||
MessageTypeUserPremiumGuildSubscription
|
||||
MessageTypeUserPremiumGuildSubscriptionTierOne
|
||||
MessageTypeUserPremiumGuildSubscriptionTierTwo
|
||||
MessageTypeUserPremiumGuildSubscriptionTierThree
|
||||
MessageTypeChannelFollowAdd
|
||||
MessageTypeGuildDiscoveryDisqualified = iota + 1
|
||||
MessageTypeGuildDiscoveryRequalified
|
||||
MessageTypeReply = iota + 4
|
||||
MessageTypeApplicationCommand
|
||||
MessageTypeDefault MessageType = 0
|
||||
MessageTypeRecipientAdd MessageType = 1
|
||||
MessageTypeRecipientRemove MessageType = 2
|
||||
MessageTypeCall MessageType = 3
|
||||
MessageTypeChannelNameChange MessageType = 4
|
||||
MessageTypeChannelIconChange MessageType = 5
|
||||
MessageTypeChannelPinnedMessage MessageType = 6
|
||||
MessageTypeGuildMemberJoin MessageType = 7
|
||||
MessageTypeUserPremiumGuildSubscription MessageType = 8
|
||||
MessageTypeUserPremiumGuildSubscriptionTierOne MessageType = 9
|
||||
MessageTypeUserPremiumGuildSubscriptionTierTwo MessageType = 10
|
||||
MessageTypeUserPremiumGuildSubscriptionTierThree MessageType = 11
|
||||
MessageTypeChannelFollowAdd MessageType = 12
|
||||
MessageTypeGuildDiscoveryDisqualified MessageType = 14
|
||||
MessageTypeGuildDiscoveryRequalified MessageType = 15
|
||||
MessageTypeThreadCreated MessageType = 18
|
||||
MessageTypeReply MessageType = 19
|
||||
MessageTypeChatInputCommand MessageType = 20
|
||||
MessageTypeThreadStarterMessage MessageType = 21
|
||||
MessageTypeContextMenuCommand MessageType = 23
|
||||
)
|
||||
|
||||
// A Message stores all data related to a specific Discord message.
|
||||
@@ -58,11 +63,11 @@ type Message struct {
|
||||
// CAUTION: this field may be removed in a
|
||||
// future API version; it is safer to calculate
|
||||
// the creation time via the ID.
|
||||
Timestamp Timestamp `json:"timestamp"`
|
||||
Timestamp time.Time `json:"timestamp"`
|
||||
|
||||
// The time at which the last edit of the message
|
||||
// occurred, if it has been edited.
|
||||
EditedTimestamp Timestamp `json:"edited_timestamp"`
|
||||
EditedTimestamp *time.Time `json:"edited_timestamp"`
|
||||
|
||||
// The roles mentioned in the message.
|
||||
MentionRoles []string `json:"mention_roles"`
|
||||
@@ -80,8 +85,10 @@ type Message struct {
|
||||
// A list of attachments present in the message.
|
||||
Attachments []*MessageAttachment `json:"attachments"`
|
||||
|
||||
// A list of embeds present in the message. Multiple
|
||||
// embeds can currently only be sent by webhooks.
|
||||
// A list of components attached to the message.
|
||||
Components []MessageComponent `json:"-"`
|
||||
|
||||
// A list of embeds present in the message.
|
||||
Embeds []*MessageEmbed `json:"embeds"`
|
||||
|
||||
// A list of users mentioned in the message.
|
||||
@@ -116,13 +123,70 @@ type Message struct {
|
||||
// Is sent with Rich Presence-related chat embeds
|
||||
Application *MessageApplication `json:"application"`
|
||||
|
||||
// MessageReference contains reference data sent with crossposted messages
|
||||
// MessageReference contains reference data sent with crossposted or reply messages.
|
||||
// This does not contain the reference *to* this message; this is for when *this* message references another.
|
||||
// To generate a reference to this message, use (*Message).Reference().
|
||||
MessageReference *MessageReference `json:"message_reference"`
|
||||
|
||||
// The message associated with the message_reference
|
||||
// NOTE: This field is only returned for messages with a type of 19 (REPLY) or 21 (THREAD_STARTER_MESSAGE).
|
||||
// If the message is a reply but the referenced_message field is not present,
|
||||
// the backend did not attempt to fetch the message that was being replied to, so its state is unknown.
|
||||
// If the field exists but is null, the referenced message was deleted.
|
||||
ReferencedMessage *Message `json:"referenced_message"`
|
||||
|
||||
// Is sent when the message is a response to an Interaction, without an existing message.
|
||||
// This means responses to message component interactions do not include this property,
|
||||
// instead including a MessageReference, as components exist on preexisting messages.
|
||||
Interaction *MessageInteraction `json:"interaction"`
|
||||
|
||||
// The flags of the message, which describe extra features of a message.
|
||||
// This is a combination of bit masks; the presence of a certain permission can
|
||||
// be checked by performing a bitwise AND between this int and the flag.
|
||||
Flags MessageFlags `json:"flags"`
|
||||
|
||||
// The thread that was started from this message, includes thread member object
|
||||
Thread *Channel `json:"thread,omitempty"`
|
||||
|
||||
// An array of Sticker objects, if any were sent.
|
||||
StickerItems []*Sticker `json:"sticker_items"`
|
||||
}
|
||||
|
||||
// UnmarshalJSON is a helper function to unmarshal the Message.
|
||||
func (m *Message) UnmarshalJSON(data []byte) error {
|
||||
type message Message
|
||||
var v struct {
|
||||
message
|
||||
RawComponents []unmarshalableMessageComponent `json:"components"`
|
||||
}
|
||||
err := json.Unmarshal(data, &v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*m = Message(v.message)
|
||||
m.Components = make([]MessageComponent, len(v.RawComponents))
|
||||
for i, v := range v.RawComponents {
|
||||
m.Components[i] = v.MessageComponent
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// GetCustomEmojis pulls out all the custom (Non-unicode) emojis from a message and returns a Slice of the Emoji struct.
|
||||
func (m *Message) GetCustomEmojis() []*Emoji {
|
||||
var toReturn []*Emoji
|
||||
emojis := EmojiRegex.FindAllString(m.Content, -1)
|
||||
if len(emojis) < 1 {
|
||||
return toReturn
|
||||
}
|
||||
for _, em := range emojis {
|
||||
parts := strings.Split(em, ":")
|
||||
toReturn = append(toReturn, &Emoji{
|
||||
ID: parts[2][:len(parts[2])-1],
|
||||
Name: parts[1],
|
||||
Animated: strings.HasPrefix(em, "<a:"),
|
||||
})
|
||||
}
|
||||
return toReturn
|
||||
}
|
||||
|
||||
// MessageFlags is the flags of "message" (see MessageFlags* consts)
|
||||
@@ -131,11 +195,24 @@ type MessageFlags int
|
||||
|
||||
// Valid MessageFlags values
|
||||
const (
|
||||
MessageFlagsCrossPosted MessageFlags = 1 << iota
|
||||
MessageFlagsIsCrossPosted
|
||||
MessageFlagsSupressEmbeds
|
||||
MessageFlagsSourceMessageDeleted
|
||||
MessageFlagsUrgent
|
||||
// MessageFlagsCrossPosted This message has been published to subscribed channels (via Channel Following).
|
||||
MessageFlagsCrossPosted MessageFlags = 1 << 0
|
||||
// MessageFlagsIsCrossPosted this message originated from a message in another channel (via Channel Following).
|
||||
MessageFlagsIsCrossPosted MessageFlags = 1 << 1
|
||||
// MessageFlagsSupressEmbeds do not include any embeds when serializing this message.
|
||||
MessageFlagsSupressEmbeds MessageFlags = 1 << 2
|
||||
// MessageFlagsSourceMessageDeleted the source message for this crosspost has been deleted (via Channel Following).
|
||||
MessageFlagsSourceMessageDeleted MessageFlags = 1 << 3
|
||||
// MessageFlagsUrgent this message came from the urgent message system.
|
||||
MessageFlagsUrgent MessageFlags = 1 << 4
|
||||
// MessageFlagsHasThread this message has an associated thread, with the same id as the message.
|
||||
MessageFlagsHasThread MessageFlags = 1 << 5
|
||||
// MessageFlagsEphemeral this message is only visible to the user who invoked the Interaction.
|
||||
MessageFlagsEphemeral MessageFlags = 1 << 6
|
||||
// MessageFlagsLoading this message is an Interaction Response and the bot is "thinking".
|
||||
MessageFlagsLoading MessageFlags = 1 << 7
|
||||
// MessageFlagsFailedToMentionSomeRolesInThread this message failed to mention some roles and add their members to the thread.
|
||||
MessageFlagsFailedToMentionSomeRolesInThread MessageFlags = 1 << 8
|
||||
)
|
||||
|
||||
// File stores info about files you e.g. send in messages.
|
||||
@@ -148,25 +225,33 @@ type File struct {
|
||||
// MessageSend stores all parameters you can send with ChannelMessageSendComplex.
|
||||
type MessageSend struct {
|
||||
Content string `json:"content,omitempty"`
|
||||
Embed *MessageEmbed `json:"embed,omitempty"`
|
||||
Embeds []*MessageEmbed `json:"embeds,omitempty"`
|
||||
TTS bool `json:"tts"`
|
||||
Components []MessageComponent `json:"components"`
|
||||
Files []*File `json:"-"`
|
||||
AllowedMentions *MessageAllowedMentions `json:"allowed_mentions,omitempty"`
|
||||
Reference *MessageReference `json:"message_reference,omitempty"`
|
||||
|
||||
// TODO: Remove this when compatibility is not required.
|
||||
File *File `json:"-"`
|
||||
|
||||
// TODO: Remove this when compatibility is not required.
|
||||
Embed *MessageEmbed `json:"-"`
|
||||
}
|
||||
|
||||
// MessageEdit is used to chain parameters via ChannelMessageEditComplex, which
|
||||
// is also where you should get the instance from.
|
||||
type MessageEdit struct {
|
||||
Content *string `json:"content,omitempty"`
|
||||
Embed *MessageEmbed `json:"embed,omitempty"`
|
||||
Components []MessageComponent `json:"components"`
|
||||
Embeds []*MessageEmbed `json:"embeds,omitempty"`
|
||||
AllowedMentions *MessageAllowedMentions `json:"allowed_mentions,omitempty"`
|
||||
|
||||
ID string
|
||||
Channel string
|
||||
|
||||
// TODO: Remove this when compatibility is not required.
|
||||
Embed *MessageEmbed `json:"-"`
|
||||
}
|
||||
|
||||
// NewMessageEdit returns a MessageEdit struct, initialized
|
||||
@@ -188,7 +273,14 @@ func (m *MessageEdit) SetContent(str string) *MessageEdit {
|
||||
// SetEmbed is a convenience function for setting the embed,
|
||||
// so you can chain commands.
|
||||
func (m *MessageEdit) SetEmbed(embed *MessageEmbed) *MessageEdit {
|
||||
m.Embed = embed
|
||||
m.Embeds = []*MessageEmbed{embed}
|
||||
return m
|
||||
}
|
||||
|
||||
// SetEmbeds is a convenience function for setting the embeds,
|
||||
// so you can chain commands.
|
||||
func (m *MessageEdit) SetEmbeds(embeds []*MessageEmbed) *MessageEdit {
|
||||
m.Embeds = embeds
|
||||
return m
|
||||
}
|
||||
|
||||
@@ -230,13 +322,15 @@ type MessageAllowedMentions struct {
|
||||
|
||||
// A MessageAttachment stores data for message attachments.
|
||||
type MessageAttachment struct {
|
||||
ID string `json:"id"`
|
||||
URL string `json:"url"`
|
||||
ProxyURL string `json:"proxy_url"`
|
||||
Filename string `json:"filename"`
|
||||
Width int `json:"width"`
|
||||
Height int `json:"height"`
|
||||
Size int `json:"size"`
|
||||
ID string `json:"id"`
|
||||
URL string `json:"url"`
|
||||
ProxyURL string `json:"proxy_url"`
|
||||
Filename string `json:"filename"`
|
||||
ContentType string `json:"content_type"`
|
||||
Width int `json:"width"`
|
||||
Height int `json:"height"`
|
||||
Size int `json:"size"`
|
||||
Ephemeral bool `json:"ephemeral"`
|
||||
}
|
||||
|
||||
// MessageEmbedFooter is a part of a MessageEmbed struct.
|
||||
@@ -339,23 +433,10 @@ type MessageActivityType int
|
||||
|
||||
// Constants for the different types of Message Activity
|
||||
const (
|
||||
MessageActivityTypeJoin MessageActivityType = iota + 1
|
||||
MessageActivityTypeSpectate
|
||||
MessageActivityTypeListen
|
||||
MessageActivityTypeJoinRequest
|
||||
)
|
||||
|
||||
// MessageFlag describes an extra feature of the message
|
||||
type MessageFlag int
|
||||
|
||||
// Constants for the different bit offsets of Message Flags
|
||||
const (
|
||||
// This message has been published to subscribed channels (via Channel Following)
|
||||
MessageFlagCrossposted MessageFlag = 1 << iota
|
||||
// This message originated from a message in another channel (via Channel Following)
|
||||
MessageFlagIsCrosspost
|
||||
// Do not include any embeds when serializing this message
|
||||
MessageFlagSuppressEmbeds
|
||||
MessageActivityTypeJoin MessageActivityType = 1
|
||||
MessageActivityTypeSpectate MessageActivityType = 2
|
||||
MessageActivityTypeListen MessageActivityType = 3
|
||||
MessageActivityTypeJoinRequest MessageActivityType = 5
|
||||
)
|
||||
|
||||
// MessageApplication is sent with Rich Presence-related chat embeds
|
||||
@@ -447,3 +528,14 @@ func (m *Message) ContentWithMoreMentionsReplaced(s *Session) (content string, e
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// MessageInteraction contains information about the application command interaction which generated the message.
|
||||
type MessageInteraction struct {
|
||||
ID string `json:"id"`
|
||||
Type InteractionType `json:"type"`
|
||||
Name string `json:"name"`
|
||||
User *User `json:"user"`
|
||||
|
||||
// Member is only present when the interaction is from a guild.
|
||||
Member *Member `json:"member"`
|
||||
}
|
||||
@@ -18,8 +18,8 @@ type MembershipState int
|
||||
|
||||
// Constants for the different stages of the MembershipState
|
||||
const (
|
||||
MembershipStateInvited MembershipState = iota + 1
|
||||
MembershipStateAccepted
|
||||
MembershipStateInvited MembershipState = 1
|
||||
MembershipStateAccepted MembershipState = 2
|
||||
)
|
||||
|
||||
// A TeamMember struct stores values for a single Team Member, extending the normal User data - note that the user field is partial
|
||||
@@ -40,28 +40,11 @@ type Team struct {
|
||||
Members []*TeamMember `json:"members"`
|
||||
}
|
||||
|
||||
// An Application struct stores values for a Discord OAuth2 Application
|
||||
type Application struct {
|
||||
ID string `json:"id,omitempty"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description,omitempty"`
|
||||
Icon string `json:"icon,omitempty"`
|
||||
Secret string `json:"secret,omitempty"`
|
||||
RedirectURIs *[]string `json:"redirect_uris,omitempty"`
|
||||
BotRequireCodeGrant bool `json:"bot_require_code_grant,omitempty"`
|
||||
BotPublic bool `json:"bot_public,omitempty"`
|
||||
RPCApplicationState int `json:"rpc_application_state,omitempty"`
|
||||
Flags int `json:"flags,omitempty"`
|
||||
Owner *User `json:"owner"`
|
||||
Bot *User `json:"bot"`
|
||||
Team *Team `json:"team"`
|
||||
}
|
||||
|
||||
// Application returns an Application structure of a specific Application
|
||||
// appID : The ID of an Application
|
||||
func (s *Session) Application(appID string) (st *Application, err error) {
|
||||
|
||||
body, err := s.RequestWithBucketID("GET", EndpointApplication(appID), nil, EndpointApplication(""))
|
||||
body, err := s.RequestWithBucketID("GET", EndpointOAuth2Application(appID), nil, EndpointOAuth2Application(""))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -73,7 +56,7 @@ func (s *Session) Application(appID string) (st *Application, err error) {
|
||||
// Applications returns all applications for the authenticated user
|
||||
func (s *Session) Applications() (st []*Application, err error) {
|
||||
|
||||
body, err := s.RequestWithBucketID("GET", EndpointApplications, nil, EndpointApplications)
|
||||
body, err := s.RequestWithBucketID("GET", EndpointOAuth2Applications, nil, EndpointOAuth2Applications)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -88,12 +71,11 @@ func (s *Session) Applications() (st []*Application, err error) {
|
||||
func (s *Session) ApplicationCreate(ap *Application) (st *Application, err error) {
|
||||
|
||||
data := struct {
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
RedirectURIs *[]string `json:"redirect_uris,omitempty"`
|
||||
}{ap.Name, ap.Description, ap.RedirectURIs}
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
}{ap.Name, ap.Description}
|
||||
|
||||
body, err := s.RequestWithBucketID("POST", EndpointApplications, data, EndpointApplications)
|
||||
body, err := s.RequestWithBucketID("POST", EndpointOAuth2Applications, data, EndpointOAuth2Applications)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -107,12 +89,11 @@ func (s *Session) ApplicationCreate(ap *Application) (st *Application, err error
|
||||
func (s *Session) ApplicationUpdate(appID string, ap *Application) (st *Application, err error) {
|
||||
|
||||
data := struct {
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
RedirectURIs *[]string `json:"redirect_uris,omitempty"`
|
||||
}{ap.Name, ap.Description, ap.RedirectURIs}
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
}{ap.Name, ap.Description}
|
||||
|
||||
body, err := s.RequestWithBucketID("PUT", EndpointApplication(appID), data, EndpointApplication(""))
|
||||
body, err := s.RequestWithBucketID("PUT", EndpointOAuth2Application(appID), data, EndpointOAuth2Application(""))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -125,7 +106,7 @@ func (s *Session) ApplicationUpdate(appID string, ap *Application) (st *Applicat
|
||||
// appID : The ID of an Application
|
||||
func (s *Session) ApplicationDelete(appID string) (err error) {
|
||||
|
||||
_, err = s.RequestWithBucketID("DELETE", EndpointApplication(appID), nil, EndpointApplication(""))
|
||||
_, err = s.RequestWithBucketID("DELETE", EndpointOAuth2Application(appID), nil, EndpointOAuth2Application(""))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -143,7 +124,7 @@ type Asset struct {
|
||||
// ApplicationAssets returns an application's assets
|
||||
func (s *Session) ApplicationAssets(appID string) (ass []*Asset, err error) {
|
||||
|
||||
body, err := s.RequestWithBucketID("GET", EndpointApplicationAssets(appID), nil, EndpointApplicationAssets(""))
|
||||
body, err := s.RequestWithBucketID("GET", EndpointOAuth2ApplicationAssets(appID), nil, EndpointOAuth2ApplicationAssets(""))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -163,7 +144,7 @@ func (s *Session) ApplicationAssets(appID string) (ass []*Asset, err error) {
|
||||
// NOTE: func name may change, if I can think up something better.
|
||||
func (s *Session) ApplicationBotCreate(appID string) (st *User, err error) {
|
||||
|
||||
body, err := s.RequestWithBucketID("POST", EndpointApplicationsBot(appID), nil, EndpointApplicationsBot(""))
|
||||
body, err := s.RequestWithBucketID("POST", EndpointOAuth2ApplicationsBot(appID), nil, EndpointOAuth2ApplicationsBot(""))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -33,7 +33,7 @@ func NewRatelimiter() *RateLimiter {
|
||||
buckets: make(map[string]*Bucket),
|
||||
global: new(int64),
|
||||
customRateLimits: []*customRateLimit{
|
||||
&customRateLimit{
|
||||
{
|
||||
suffix: "//reactions//",
|
||||
requests: 1,
|
||||
reset: 200 * time.Millisecond,
|
||||
File diff suppressed because it is too large
Load Diff
@@ -38,13 +38,15 @@ type State struct {
|
||||
Ready
|
||||
|
||||
// MaxMessageCount represents how many messages per channel the state will store.
|
||||
MaxMessageCount int
|
||||
TrackChannels bool
|
||||
TrackEmojis bool
|
||||
TrackMembers bool
|
||||
TrackRoles bool
|
||||
TrackVoice bool
|
||||
TrackPresences bool
|
||||
MaxMessageCount int
|
||||
TrackChannels bool
|
||||
TrackThreads bool
|
||||
TrackEmojis bool
|
||||
TrackMembers bool
|
||||
TrackThreadMembers bool
|
||||
TrackRoles bool
|
||||
TrackVoice bool
|
||||
TrackPresences bool
|
||||
|
||||
guildMap map[string]*Guild
|
||||
channelMap map[string]*Channel
|
||||
@@ -58,15 +60,17 @@ func NewState() *State {
|
||||
PrivateChannels: []*Channel{},
|
||||
Guilds: []*Guild{},
|
||||
},
|
||||
TrackChannels: true,
|
||||
TrackEmojis: true,
|
||||
TrackMembers: true,
|
||||
TrackRoles: true,
|
||||
TrackVoice: true,
|
||||
TrackPresences: true,
|
||||
guildMap: make(map[string]*Guild),
|
||||
channelMap: make(map[string]*Channel),
|
||||
memberMap: make(map[string]map[string]*Member),
|
||||
TrackChannels: true,
|
||||
TrackThreads: true,
|
||||
TrackEmojis: true,
|
||||
TrackMembers: true,
|
||||
TrackThreadMembers: true,
|
||||
TrackRoles: true,
|
||||
TrackVoice: true,
|
||||
TrackPresences: true,
|
||||
guildMap: make(map[string]*Guild),
|
||||
channelMap: make(map[string]*Channel),
|
||||
memberMap: make(map[string]map[string]*Member),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,6 +97,11 @@ func (s *State) GuildAdd(guild *Guild) error {
|
||||
s.channelMap[c.ID] = c
|
||||
}
|
||||
|
||||
// Add all the threads to the state in case of thread sync list.
|
||||
for _, t := range guild.Threads {
|
||||
s.channelMap[t.ID] = t
|
||||
}
|
||||
|
||||
// If this guild contains a new member slice, we must regenerate the member map so the pointers stay valid
|
||||
if guild.Members != nil {
|
||||
s.createMemberMap(guild)
|
||||
@@ -122,6 +131,9 @@ func (s *State) GuildAdd(guild *Guild) error {
|
||||
if guild.Channels == nil {
|
||||
guild.Channels = g.Channels
|
||||
}
|
||||
if guild.Threads == nil {
|
||||
guild.Threads = g.Threads
|
||||
}
|
||||
if guild.VoiceStates == nil {
|
||||
guild.VoiceStates = g.VoiceStates
|
||||
}
|
||||
@@ -180,21 +192,12 @@ func (s *State) Guild(guildID string) (*Guild, error) {
|
||||
return nil, ErrStateNotFound
|
||||
}
|
||||
|
||||
// PresenceAdd adds a presence to the current world state, or
|
||||
// updates it if it already exists.
|
||||
func (s *State) PresenceAdd(guildID string, presence *Presence) error {
|
||||
if s == nil {
|
||||
return ErrNilState
|
||||
func (s *State) presenceAdd(guildID string, presence *Presence) error {
|
||||
guild, ok := s.guildMap[guildID]
|
||||
if !ok {
|
||||
return ErrStateNotFound
|
||||
}
|
||||
|
||||
guild, err := s.Guild(guildID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
|
||||
for i, p := range guild.Presences {
|
||||
if p.User.ID == presence.User.ID {
|
||||
//guild.Presences[i] = presence
|
||||
@@ -233,6 +236,19 @@ func (s *State) PresenceAdd(guildID string, presence *Presence) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// PresenceAdd adds a presence to the current world state, or
|
||||
// updates it if it already exists.
|
||||
func (s *State) PresenceAdd(guildID string, presence *Presence) error {
|
||||
if s == nil {
|
||||
return ErrNilState
|
||||
}
|
||||
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
|
||||
return s.presenceAdd(guildID, presence)
|
||||
}
|
||||
|
||||
// PresenceRemove removes a presence from the current world state.
|
||||
func (s *State) PresenceRemove(guildID string, presence *Presence) error {
|
||||
if s == nil {
|
||||
@@ -279,21 +295,12 @@ func (s *State) Presence(guildID, userID string) (*Presence, error) {
|
||||
|
||||
// TODO: Consider moving Guild state update methods onto *Guild.
|
||||
|
||||
// MemberAdd adds a member to the current world state, or
|
||||
// updates it if it already exists.
|
||||
func (s *State) MemberAdd(member *Member) error {
|
||||
if s == nil {
|
||||
return ErrNilState
|
||||
func (s *State) memberAdd(member *Member) error {
|
||||
guild, ok := s.guildMap[member.GuildID]
|
||||
if !ok {
|
||||
return ErrStateNotFound
|
||||
}
|
||||
|
||||
guild, err := s.Guild(member.GuildID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
|
||||
members, ok := s.memberMap[member.GuildID]
|
||||
if !ok {
|
||||
return ErrStateNotFound
|
||||
@@ -306,15 +313,27 @@ func (s *State) MemberAdd(member *Member) error {
|
||||
} else {
|
||||
// We are about to replace `m` in the state with `member`, but first we need to
|
||||
// make sure we preserve any fields that the `member` doesn't contain from `m`.
|
||||
if member.JoinedAt == "" {
|
||||
if member.JoinedAt.IsZero() {
|
||||
member.JoinedAt = m.JoinedAt
|
||||
}
|
||||
*m = *member
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// MemberAdd adds a member to the current world state, or
|
||||
// updates it if it already exists.
|
||||
func (s *State) MemberAdd(member *Member) error {
|
||||
if s == nil {
|
||||
return ErrNilState
|
||||
}
|
||||
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
|
||||
return s.memberAdd(member)
|
||||
}
|
||||
|
||||
// MemberRemove removes a member from current world state.
|
||||
func (s *State) MemberRemove(member *Member) error {
|
||||
if s == nil {
|
||||
@@ -465,6 +484,9 @@ func (s *State) ChannelAdd(channel *Channel) error {
|
||||
if channel.PermissionOverwrites == nil {
|
||||
channel.PermissionOverwrites = c.PermissionOverwrites
|
||||
}
|
||||
if channel.ThreadMetadata == nil {
|
||||
channel.ThreadMetadata = c.ThreadMetadata
|
||||
}
|
||||
|
||||
*c = *channel
|
||||
return nil
|
||||
@@ -472,12 +494,18 @@ func (s *State) ChannelAdd(channel *Channel) error {
|
||||
|
||||
if channel.Type == ChannelTypeDM || channel.Type == ChannelTypeGroupDM {
|
||||
s.PrivateChannels = append(s.PrivateChannels, channel)
|
||||
} else {
|
||||
guild, ok := s.guildMap[channel.GuildID]
|
||||
if !ok {
|
||||
return ErrStateNotFound
|
||||
}
|
||||
s.channelMap[channel.ID] = channel
|
||||
return nil
|
||||
}
|
||||
|
||||
guild, ok := s.guildMap[channel.GuildID]
|
||||
if !ok {
|
||||
return ErrStateNotFound
|
||||
}
|
||||
|
||||
if channel.IsThread() {
|
||||
guild.Threads = append(guild.Threads, channel)
|
||||
} else {
|
||||
guild.Channels = append(guild.Channels, channel)
|
||||
}
|
||||
|
||||
@@ -507,15 +535,26 @@ func (s *State) ChannelRemove(channel *Channel) error {
|
||||
break
|
||||
}
|
||||
}
|
||||
} else {
|
||||
guild, err := s.Guild(channel.GuildID)
|
||||
if err != nil {
|
||||
return err
|
||||
delete(s.channelMap, channel.ID)
|
||||
return nil
|
||||
}
|
||||
|
||||
guild, err := s.Guild(channel.GuildID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
|
||||
if channel.IsThread() {
|
||||
for i, t := range guild.Threads {
|
||||
if t.ID == channel.ID {
|
||||
guild.Threads = append(guild.Threads[:i], guild.Threads[i+1:]...)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
|
||||
} else {
|
||||
for i, c := range guild.Channels {
|
||||
if c.ID == channel.ID {
|
||||
guild.Channels = append(guild.Channels[:i], guild.Channels[i+1:]...)
|
||||
@@ -529,6 +568,99 @@ func (s *State) ChannelRemove(channel *Channel) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ThreadListSync syncs guild threads with provided ones.
|
||||
func (s *State) ThreadListSync(tls *ThreadListSync) error {
|
||||
guild, err := s.Guild(tls.GuildID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
|
||||
// This algorithm filters out archived or
|
||||
// threads which are children of channels in channelIDs
|
||||
// and then it adds all synced threads to guild threads and cache
|
||||
index := 0
|
||||
outer:
|
||||
for _, t := range guild.Threads {
|
||||
if !t.ThreadMetadata.Archived && tls.ChannelIDs != nil {
|
||||
for _, v := range tls.ChannelIDs {
|
||||
if t.ParentID == v {
|
||||
delete(s.channelMap, t.ID)
|
||||
continue outer
|
||||
}
|
||||
}
|
||||
guild.Threads[index] = t
|
||||
index++
|
||||
} else {
|
||||
delete(s.channelMap, t.ID)
|
||||
}
|
||||
}
|
||||
guild.Threads = guild.Threads[:index]
|
||||
for _, t := range tls.Threads {
|
||||
s.channelMap[t.ID] = t
|
||||
guild.Threads = append(guild.Threads, t)
|
||||
}
|
||||
|
||||
for _, m := range tls.Members {
|
||||
if c, ok := s.channelMap[m.ID]; ok {
|
||||
c.Member = m
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ThreadMembersUpdate updates thread members list
|
||||
func (s *State) ThreadMembersUpdate(tmu *ThreadMembersUpdate) error {
|
||||
thread, err := s.Channel(tmu.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
|
||||
for idx, member := range thread.Members {
|
||||
for _, removedMember := range tmu.RemovedMembers {
|
||||
if member.ID == removedMember {
|
||||
thread.Members = append(thread.Members[:idx], thread.Members[idx+1:]...)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, addedMember := range tmu.AddedMembers {
|
||||
thread.Members = append(thread.Members, addedMember.ThreadMember)
|
||||
if addedMember.Member != nil {
|
||||
err = s.memberAdd(addedMember.Member)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if addedMember.Presence != nil {
|
||||
err = s.presenceAdd(tmu.GuildID, addedMember.Presence)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
thread.MemberCount = tmu.MemberCount
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ThreadMemberUpdate sets or updates member data for the current user.
|
||||
func (s *State) ThreadMemberUpdate(mu *ThreadMemberUpdate) error {
|
||||
thread, err := s.Channel(mu.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
thread.Member = mu.ThreadMember
|
||||
return nil
|
||||
}
|
||||
|
||||
// GuildChannel gets a channel by ID from a guild.
|
||||
// This method is Deprecated, use Channel(channelID)
|
||||
func (s *State) GuildChannel(guildID, channelID string) (*Channel, error) {
|
||||
@@ -637,7 +769,7 @@ func (s *State) MessageAdd(message *Message) error {
|
||||
if message.Content != "" {
|
||||
m.Content = message.Content
|
||||
}
|
||||
if message.EditedTimestamp != "" {
|
||||
if message.EditedTimestamp != nil {
|
||||
m.EditedTimestamp = message.EditedTimestamp
|
||||
}
|
||||
if message.Mentions != nil {
|
||||
@@ -649,12 +781,15 @@ func (s *State) MessageAdd(message *Message) error {
|
||||
if message.Attachments != nil {
|
||||
m.Attachments = message.Attachments
|
||||
}
|
||||
if message.Timestamp != "" {
|
||||
if !message.Timestamp.IsZero() {
|
||||
m.Timestamp = message.Timestamp
|
||||
}
|
||||
if message.Author != nil {
|
||||
m.Author = message.Author
|
||||
}
|
||||
if message.Components != nil {
|
||||
m.Components = message.Components
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -665,6 +800,7 @@ func (s *State) MessageAdd(message *Message) error {
|
||||
if len(c.Messages) > s.MaxMessageCount {
|
||||
c.Messages = c.Messages[len(c.Messages)-s.MaxMessageCount:]
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -690,6 +826,7 @@ func (s *State) messageRemoveByID(channelID, messageID string) error {
|
||||
for i, m := range c.Messages {
|
||||
if m.ID == messageID {
|
||||
c.Messages = append(c.Messages[:i], c.Messages[i+1:]...)
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
@@ -833,6 +970,13 @@ func (s *State) OnInterface(se *Session, i interface{}) (err error) {
|
||||
case *GuildUpdate:
|
||||
err = s.GuildAdd(t.Guild)
|
||||
case *GuildDelete:
|
||||
var old *Guild
|
||||
old, err = s.Guild(t.ID)
|
||||
if err == nil {
|
||||
oldCopy := *old
|
||||
t.BeforeDelete = &oldCopy
|
||||
}
|
||||
|
||||
err = s.GuildRemove(t.Guild)
|
||||
case *GuildMemberAdd:
|
||||
// Updates the MemberCount of the guild.
|
||||
@@ -903,6 +1047,35 @@ func (s *State) OnInterface(se *Session, i interface{}) (err error) {
|
||||
if s.TrackChannels {
|
||||
err = s.ChannelRemove(t.Channel)
|
||||
}
|
||||
case *ThreadCreate:
|
||||
if s.TrackThreads {
|
||||
err = s.ChannelAdd(t.Channel)
|
||||
}
|
||||
case *ThreadUpdate:
|
||||
if s.TrackThreads {
|
||||
old, err := s.Channel(t.ID)
|
||||
if err == nil {
|
||||
oldCopy := *old
|
||||
t.BeforeUpdate = &oldCopy
|
||||
}
|
||||
err = s.ChannelAdd(t.Channel)
|
||||
}
|
||||
case *ThreadDelete:
|
||||
if s.TrackThreads {
|
||||
err = s.ChannelRemove(t.Channel)
|
||||
}
|
||||
case *ThreadMemberUpdate:
|
||||
if s.TrackThreads {
|
||||
err = s.ThreadMemberUpdate(t)
|
||||
}
|
||||
case *ThreadMembersUpdate:
|
||||
if s.TrackThreadMembers {
|
||||
err = s.ThreadMembersUpdate(t)
|
||||
}
|
||||
case *ThreadListSync:
|
||||
if s.TrackThreads {
|
||||
err = s.ThreadListSync(t)
|
||||
}
|
||||
case *MessageCreate:
|
||||
if s.MaxMessageCount != 0 {
|
||||
err = s.MessageAdd(t.Message)
|
||||
2038
vendor/github.com/bwmarrin/discordgo/structs.go
generated
vendored
Normal file
2038
vendor/github.com/bwmarrin/discordgo/structs.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
@@ -12,18 +12,8 @@ package discordgo
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Timestamp stores a timestamp, as sent by the Discord API.
|
||||
type Timestamp string
|
||||
|
||||
// Parse parses a timestamp string into a time.Time object.
|
||||
// The only time this can fail is if Discord changes their timestamp format.
|
||||
func (t Timestamp) Parse() (time.Time, error) {
|
||||
return time.Parse(time.RFC3339, string(t))
|
||||
}
|
||||
|
||||
// RESTError stores error information about a request with a bad response code.
|
||||
// Message is not always present, there are cases where api calls can fail
|
||||
// without returning a json message.
|
||||
@@ -1,26 +1,25 @@
|
||||
package discordgo
|
||||
|
||||
import "strings"
|
||||
|
||||
// UserFlags is the flags of "user" (see UserFlags* consts)
|
||||
// https://discord.com/developers/docs/resources/user#user-object-user-flags
|
||||
type UserFlags int
|
||||
|
||||
// Valid UserFlags values
|
||||
const (
|
||||
UserFlagDiscordEmployee UserFlags = 1 << 0
|
||||
UserFlagDiscordPartner = 1 << 1
|
||||
UserFlagHypeSquadEvents = 1 << 2
|
||||
UserFlagBugHunterLevel1 = 1 << 3
|
||||
UserFlagHouseBravery = 1 << 6
|
||||
UserFlagHouseBrilliance = 1 << 7
|
||||
UserFlagHouseBalance = 1 << 8
|
||||
UserFlagEarlySupporter = 1 << 9
|
||||
UserFlagTeamUser = 1 << 10
|
||||
UserFlagSystem = 1 << 12
|
||||
UserFlagBugHunterLevel2 = 1 << 14
|
||||
UserFlagVerifiedBot = 1 << 16
|
||||
UserFlagVerifiedBotDeveloper = 1 << 17
|
||||
UserFlagDiscordEmployee UserFlags = 1 << 0
|
||||
UserFlagDiscordPartner UserFlags = 1 << 1
|
||||
UserFlagHypeSquadEvents UserFlags = 1 << 2
|
||||
UserFlagBugHunterLevel1 UserFlags = 1 << 3
|
||||
UserFlagHouseBravery UserFlags = 1 << 6
|
||||
UserFlagHouseBrilliance UserFlags = 1 << 7
|
||||
UserFlagHouseBalance UserFlags = 1 << 8
|
||||
UserFlagEarlySupporter UserFlags = 1 << 9
|
||||
UserFlagTeamUser UserFlags = 1 << 10
|
||||
UserFlagSystem UserFlags = 1 << 12
|
||||
UserFlagBugHunterLevel2 UserFlags = 1 << 14
|
||||
UserFlagVerifiedBot UserFlags = 1 << 16
|
||||
UserFlagVerifiedBotDeveloper UserFlags = 1 << 17
|
||||
UserFlagDiscordCertifiedModerator UserFlags = 1 << 18
|
||||
)
|
||||
|
||||
// A User stores all data for an individual Discord user.
|
||||
@@ -55,6 +54,12 @@ type User struct {
|
||||
// Whether the user has multi-factor authentication enabled.
|
||||
MFAEnabled bool `json:"mfa_enabled"`
|
||||
|
||||
// The hash of the user's banner image.
|
||||
Banner string `json:"banner"`
|
||||
|
||||
// User's banner color, encoded as an integer representation of hexadecimal color code
|
||||
AccentColor int `json:"accent_color"`
|
||||
|
||||
// Whether the user is a bot.
|
||||
Bot bool `json:"bot"`
|
||||
|
||||
@@ -90,17 +95,13 @@ func (u *User) Mention() string {
|
||||
// if size is an empty string, no size parameter will
|
||||
// be added to the URL.
|
||||
func (u *User) AvatarURL(size string) string {
|
||||
var URL string
|
||||
if u.Avatar == "" {
|
||||
URL = EndpointDefaultUserAvatar(u.Discriminator)
|
||||
} else if strings.HasPrefix(u.Avatar, "a_") {
|
||||
URL = EndpointUserAvatarAnimated(u.ID, u.Avatar)
|
||||
} else {
|
||||
URL = EndpointUserAvatar(u.ID, u.Avatar)
|
||||
}
|
||||
|
||||
if size != "" {
|
||||
return URL + "?size=" + size
|
||||
}
|
||||
return URL
|
||||
return avatarURL(u.Avatar, EndpointDefaultUserAvatar(u.Discriminator),
|
||||
EndpointUserAvatar(u.ID, u.Avatar), EndpointUserAvatarAnimated(u.ID, u.Avatar), size)
|
||||
}
|
||||
|
||||
// BannerURL returns the URL of the users's banner image.
|
||||
// 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 (u *User) BannerURL(size string) string {
|
||||
return bannerURL(u.Banner, EndpointUserBanner(u.ID, u.Banner), EndpointUserBannerAnimated(u.ID, u.Banner), size)
|
||||
}
|
||||
110
vendor/github.com/bwmarrin/discordgo/util.go
generated
vendored
Normal file
110
vendor/github.com/bwmarrin/discordgo/util.go
generated
vendored
Normal file
@@ -0,0 +1,110 @@
|
||||
package discordgo
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"mime/multipart"
|
||||
"net/textproto"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// SnowflakeTimestamp returns the creation time of a Snowflake ID relative to the creation of Discord.
|
||||
func SnowflakeTimestamp(ID string) (t time.Time, err error) {
|
||||
i, err := strconv.ParseInt(ID, 10, 64)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
timestamp := (i >> 22) + 1420070400000
|
||||
t = time.Unix(0, timestamp*1000000)
|
||||
return
|
||||
}
|
||||
|
||||
// MultipartBodyWithJSON returns the contentType and body for a discord request
|
||||
// data : The object to encode for payload_json in the multipart request
|
||||
// files : Files to include in the request
|
||||
func MultipartBodyWithJSON(data interface{}, files []*File) (requestContentType string, requestBody []byte, err error) {
|
||||
body := &bytes.Buffer{}
|
||||
bodywriter := multipart.NewWriter(body)
|
||||
|
||||
payload, err := json.Marshal(data)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
var p io.Writer
|
||||
|
||||
h := make(textproto.MIMEHeader)
|
||||
h.Set("Content-Disposition", `form-data; name="payload_json"`)
|
||||
h.Set("Content-Type", "application/json")
|
||||
|
||||
p, err = bodywriter.CreatePart(h)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if _, err = p.Write(payload); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
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)))
|
||||
contentType := file.ContentType
|
||||
if contentType == "" {
|
||||
contentType = "application/octet-stream"
|
||||
}
|
||||
h.Set("Content-Type", contentType)
|
||||
|
||||
p, err = bodywriter.CreatePart(h)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if _, err = io.Copy(p, file.Reader); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
err = bodywriter.Close()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return bodywriter.FormDataContentType(), body.Bytes(), nil
|
||||
}
|
||||
|
||||
func avatarURL(avatarHash, defaultAvatarURL, staticAvatarURL, animatedAvatarURL, size string) string {
|
||||
var URL string
|
||||
if avatarHash == "" {
|
||||
URL = defaultAvatarURL
|
||||
} else if strings.HasPrefix(avatarHash, "a_") {
|
||||
URL = animatedAvatarURL
|
||||
} else {
|
||||
URL = staticAvatarURL
|
||||
}
|
||||
|
||||
if size != "" {
|
||||
return URL + "?size=" + size
|
||||
}
|
||||
return URL
|
||||
}
|
||||
|
||||
func bannerURL(bannerHash, staticBannerURL, animatedBannerURL, size string) string {
|
||||
var URL string
|
||||
if bannerHash == "" {
|
||||
return ""
|
||||
} else if strings.HasPrefix(bannerHash, "a_") {
|
||||
URL = animatedBannerURL
|
||||
} else {
|
||||
URL = staticBannerURL
|
||||
}
|
||||
|
||||
if size != "" {
|
||||
return URL + "?size=" + size
|
||||
}
|
||||
return URL
|
||||
}
|
||||
@@ -831,9 +831,15 @@ func (v *VoiceConnection) opusReceiver(udpConn *net.UDPConn, close <-chan struct
|
||||
copy(nonce[:], recvbuf[0:12])
|
||||
p.Opus, _ = secretbox.Open(nil, recvbuf[12:rlen], &nonce, &v.op4.SecretKey)
|
||||
|
||||
if len(p.Opus) > 8 && recvbuf[0] == 0x90 {
|
||||
// Extension bit is set, first 8 bytes is the extended header
|
||||
p.Opus = p.Opus[8:]
|
||||
// extension bit set, and not a RTCP packet
|
||||
if ((recvbuf[0] & 0x10) == 0x10) && ((recvbuf[1] & 0x80) == 0) {
|
||||
// get extended header length
|
||||
extlen := binary.BigEndian.Uint16(p.Opus[2:4])
|
||||
// 4 bytes (ext header header) + 4*extlen (ext header data)
|
||||
shift := int(4 + 4*extlen)
|
||||
if len(p.Opus) > shift {
|
||||
p.Opus = p.Opus[shift:]
|
||||
}
|
||||
}
|
||||
|
||||
if c != nil {
|
||||
49
vendor/github.com/bwmarrin/discordgo/webhook.go
generated
vendored
Normal file
49
vendor/github.com/bwmarrin/discordgo/webhook.go
generated
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
package discordgo
|
||||
|
||||
// Webhook stores the data for a webhook.
|
||||
type Webhook struct {
|
||||
ID string `json:"id"`
|
||||
Type WebhookType `json:"type"`
|
||||
GuildID string `json:"guild_id"`
|
||||
ChannelID string `json:"channel_id"`
|
||||
User *User `json:"user"`
|
||||
Name string `json:"name"`
|
||||
Avatar string `json:"avatar"`
|
||||
Token string `json:"token"`
|
||||
|
||||
// ApplicationID is the bot/OAuth2 application that created this webhook
|
||||
ApplicationID string `json:"application_id,omitempty"`
|
||||
}
|
||||
|
||||
// WebhookType is the type of Webhook (see WebhookType* consts) in the Webhook struct
|
||||
// https://discord.com/developers/docs/resources/webhook#webhook-object-webhook-types
|
||||
type WebhookType int
|
||||
|
||||
// Valid WebhookType values
|
||||
const (
|
||||
WebhookTypeIncoming WebhookType = 1
|
||||
WebhookTypeChannelFollower WebhookType = 2
|
||||
)
|
||||
|
||||
// WebhookParams is a struct for webhook params, used in the WebhookExecute command.
|
||||
type WebhookParams struct {
|
||||
Content string `json:"content,omitempty"`
|
||||
Username string `json:"username,omitempty"`
|
||||
AvatarURL string `json:"avatar_url,omitempty"`
|
||||
TTS bool `json:"tts,omitempty"`
|
||||
Files []*File `json:"-"`
|
||||
Components []MessageComponent `json:"components"`
|
||||
Embeds []*MessageEmbed `json:"embeds,omitempty"`
|
||||
AllowedMentions *MessageAllowedMentions `json:"allowed_mentions,omitempty"`
|
||||
// NOTE: Works only for followup messages.
|
||||
Flags uint64 `json:"flags,omitempty"`
|
||||
}
|
||||
|
||||
// WebhookEdit stores data for editing of a webhook message.
|
||||
type WebhookEdit struct {
|
||||
Content string `json:"content,omitempty"`
|
||||
Components []MessageComponent `json:"components"`
|
||||
Embeds []*MessageEmbed `json:"embeds,omitempty"`
|
||||
Files []*File `json:"-"`
|
||||
AllowedMentions *MessageAllowedMentions `json:"allowed_mentions,omitempty"`
|
||||
}
|
||||
@@ -33,7 +33,7 @@ var ErrWSAlreadyOpen = errors.New("web socket already opened")
|
||||
var ErrWSNotFound = errors.New("no websocket connection exists")
|
||||
|
||||
// ErrWSShardBounds is thrown when you try to use a shard ID that is
|
||||
// less than the total shard count
|
||||
// more than the total shard count
|
||||
var ErrWSShardBounds = errors.New("ShardID must be less than ShardCount")
|
||||
|
||||
type resumePacket struct {
|
||||
@@ -383,6 +383,17 @@ func (s *Session) UpdateListeningStatus(name string) (err error) {
|
||||
|
||||
// UpdateStatusComplex allows for sending the raw status update data untouched by discordgo.
|
||||
func (s *Session) UpdateStatusComplex(usd UpdateStatusData) (err error) {
|
||||
// The comment does say "untouched by discordgo", but we might need to lie a bit here.
|
||||
// The Discord documentation lists `activities` as being nullable, but in practice this
|
||||
// doesn't seem to be the case. I had filed an issue about this at
|
||||
// https://github.com/discord/discord-api-docs/issues/2559, but as of writing this
|
||||
// haven't had any movement on it, so at this point I'm assuming this is an error,
|
||||
// and am fixing this bug accordingly. Because sending `null` for `activities` instantly
|
||||
// disconnects us, I think that disallowing it from being sent in `UpdateStatusComplex`
|
||||
// isn't that big of an issue.
|
||||
if usd.Activities == nil {
|
||||
usd.Activities = make([]*Activity, 0)
|
||||
}
|
||||
|
||||
s.RLock()
|
||||
defer s.RUnlock()
|
||||
@@ -755,13 +766,13 @@ func (s *Session) identify() error {
|
||||
s.log(LogDebug, "called")
|
||||
|
||||
// TODO: This is a temporary block of code to help
|
||||
// maintain backwards compatability
|
||||
// maintain backwards compatibility
|
||||
if s.Compress == false {
|
||||
s.Identify.Compress = false
|
||||
}
|
||||
|
||||
// TODO: This is a temporary block of code to help
|
||||
// maintain backwards compatability
|
||||
// maintain backwards compatibility
|
||||
if s.Token != "" && s.Identify.Token == "" {
|
||||
s.Identify.Token = s.Token
|
||||
}
|
||||
3
vendor/github.com/d5/tengo/v2/README.md
generated
vendored
3
vendor/github.com/d5/tengo/v2/README.md
generated
vendored
@@ -147,7 +147,4 @@ fmt.Println(res) // "success"
|
||||
- Syntax Highlighters: [VSCode](https://github.com/lissein/vscode-tengo), [Atom](https://github.com/d5/tengo-atom)
|
||||
- **Why the name Tengo?** It's from [1Q84](https://en.wikipedia.org/wiki/1Q84).
|
||||
|
||||
##
|
||||
|
||||
:hearts: Like writing Go code? Come work at Skool. [We're hiring!](https://jobs.lever.co/skool)
|
||||
|
||||
|
||||
7
vendor/github.com/d5/tengo/v2/objects.go
generated
vendored
7
vendor/github.com/d5/tengo/v2/objects.go
generated
vendored
@@ -1577,9 +1577,8 @@ func (o *Undefined) Value() Object {
|
||||
// UserFunction represents a user function.
|
||||
type UserFunction struct {
|
||||
ObjectImpl
|
||||
Name string
|
||||
Value CallableFunc
|
||||
EncodingID string
|
||||
Name string
|
||||
Value CallableFunc
|
||||
}
|
||||
|
||||
// TypeName returns the name of the type.
|
||||
@@ -1593,7 +1592,7 @@ func (o *UserFunction) String() string {
|
||||
|
||||
// Copy returns a copy of the type.
|
||||
func (o *UserFunction) Copy() Object {
|
||||
return &UserFunction{Value: o.Value}
|
||||
return &UserFunction{Value: o.Value, Name: o.Name}
|
||||
}
|
||||
|
||||
// Equals returns true if the value of the type is equal to the value of
|
||||
|
||||
2
vendor/github.com/d5/tengo/v2/stdlib/source_modules.go
generated
vendored
2
vendor/github.com/d5/tengo/v2/stdlib/source_modules.go
generated
vendored
@@ -4,5 +4,5 @@ package stdlib
|
||||
|
||||
// SourceModules are source type standard library modules.
|
||||
var SourceModules = map[string]string{
|
||||
"enum": "is_enumerable := func(x) {\n return is_array(x) || is_map(x) || is_immutable_array(x) || is_immutable_map(x)\n}\n\nis_array_like := func(x) {\n return is_array(x) || is_immutable_array(x)\n}\n\nexport {\n // all returns true if the given function `fn` evaluates to a truthy value on\n // all of the items in `x`. It returns undefined if `x` is not enumerable.\n all: func(x, fn) {\n if !is_enumerable(x) { return undefined }\n\n for k, v in x {\n if !fn(k, v) { return false }\n }\n\n return true\n },\n // any returns true if the given function `fn` evaluates to a truthy value on\n // any of the items in `x`. It returns undefined if `x` is not enumerable.\n any: func(x, fn) {\n if !is_enumerable(x) { return undefined }\n\n for k, v in x {\n if fn(k, v) { return true }\n }\n\n return false\n },\n // chunk returns an array of elements split into groups the length of size.\n // If `x` can't be split evenly, the final chunk will be the remaining elements.\n // It returns undefined if `x` is not array.\n chunk: func(x, size) {\n if !is_array_like(x) || !size { return undefined }\n\n numElements := len(x)\n if !numElements { return [] }\n\n res := []\n idx := 0\n for idx < numElements {\n res = append(res, x[idx:idx+size])\n idx += size\n }\n\n return res\n },\n // at returns an element at the given index (if `x` is array) or\n // key (if `x` is map). It returns undefined if `x` is not enumerable.\n at: func(x, key) {\n if !is_enumerable(x) { return undefined }\n\n if is_array_like(x) {\n if !is_int(key) { return undefined }\n } else {\n if !is_string(key) { return undefined }\n }\n\n return x[key]\n },\n // each iterates over elements of `x` and invokes `fn` for each element. `fn` is\n // invoked with two arguments: `key` and `value`. `key` is an int index\n // if `x` is array. `key` is a string key if `x` is map. It does not iterate\n // and returns undefined if `x` is not enumerable.\n each: func(x, fn) {\n if !is_enumerable(x) { return undefined }\n\n for k, v in x {\n fn(k, v)\n }\n },\n // filter iterates over elements of `x`, returning an array of all elements `fn`\n // returns truthy for. `fn` is invoked with two arguments: `key` and `value`.\n // `key` is an int index if `x` is array. `key` is a string key if `x` is map.\n // It returns undefined if `x` is not enumerable.\n filter: func(x, fn) {\n if !is_array_like(x) { return undefined }\n\n dst := []\n for k, v in x {\n if fn(k, v) { dst = append(dst, v) }\n }\n\n return dst\n },\n // find iterates over elements of `x`, returning value of the first element `fn`\n // returns truthy for. `fn` is invoked with two arguments: `key` and `value`.\n // `key` is an int index if `x` is array. `key` is a string key if `x` is map.\n // It returns undefined if `x` is not enumerable.\n find: func(x, fn) {\n if !is_enumerable(x) { return undefined }\n\n for k, v in x {\n if fn(k, v) { return v }\n }\n },\n // find_key iterates over elements of `x`, returning key or index of the first\n // element `fn` returns truthy for. `fn` is invoked with two arguments: `key`\n // and `value`. `key` is an int index if `x` is array. `key` is a string key if\n // `x` is map. It returns undefined if `x` is not enumerable.\n find_key: func(x, fn) {\n if !is_enumerable(x) { return undefined }\n\n for k, v in x {\n if fn(k, v) { return k }\n }\n },\n // map creates an array of values by running each element in `x` through `fn`.\n // `fn` is invoked with two arguments: `key` and `value`. `key` is an int index\n // if `x` is array. `key` is a string key if `x` is map. It returns undefined\n // if `x` is not enumerable.\n map: func(x, fn) {\n if !is_enumerable(x) { return undefined }\n\n dst := []\n for k, v in x {\n dst = append(dst, fn(k, v))\n }\n\n return dst\n },\n // key returns the first argument.\n key: func(k, _) { return k },\n // value returns the second argument.\n value: func(_, v) { return v }\n}\n",
|
||||
"enum": "is_enumerable := func(x) {\n return is_array(x) || is_map(x) || is_immutable_array(x) || is_immutable_map(x)\n}\n\nis_array_like := func(x) {\n return is_array(x) || is_immutable_array(x)\n}\n\nexport {\n // all returns true if the given function `fn` evaluates to a truthy value on\n // all of the items in `x`. It returns undefined if `x` is not enumerable.\n all: func(x, fn) {\n if !is_enumerable(x) { return undefined }\n\n for k, v in x {\n if !fn(k, v) { return false }\n }\n\n return true\n },\n // any returns true if the given function `fn` evaluates to a truthy value on\n // any of the items in `x`. It returns undefined if `x` is not enumerable.\n any: func(x, fn) {\n if !is_enumerable(x) { return undefined }\n\n for k, v in x {\n if fn(k, v) { return true }\n }\n\n return false\n },\n // chunk returns an array of elements split into groups the length of size.\n // If `x` can't be split evenly, the final chunk will be the remaining elements.\n // It returns undefined if `x` is not array.\n chunk: func(x, size) {\n if !is_array_like(x) || !size { return undefined }\n\n numElements := len(x)\n if !numElements { return [] }\n\n res := []\n idx := 0\n for idx < numElements {\n res = append(res, x[idx:idx+size])\n idx += size\n }\n\n return res\n },\n // at returns an element at the given index (if `x` is array) or\n // key (if `x` is map). It returns undefined if `x` is not enumerable.\n at: func(x, key) {\n if !is_enumerable(x) { return undefined }\n\n if is_array_like(x) {\n if !is_int(key) { return undefined }\n } else {\n if !is_string(key) { return undefined }\n }\n\n return x[key]\n },\n // each iterates over elements of `x` and invokes `fn` for each element. `fn` is\n // invoked with two arguments: `key` and `value`. `key` is an int index\n // if `x` is array. `key` is a string key if `x` is map. It does not iterate\n // and returns undefined if `x` is not enumerable.\n each: func(x, fn) {\n if !is_enumerable(x) { return undefined }\n\n for k, v in x {\n fn(k, v)\n }\n },\n // filter iterates over elements of `x`, returning an array of all elements `fn`\n // returns truthy for. `fn` is invoked with two arguments: `key` and `value`.\n // `key` is an int index if `x` is array. It returns undefined if `x` is not array.\n filter: func(x, fn) {\n if !is_array_like(x) { return undefined }\n\n dst := []\n for k, v in x {\n if fn(k, v) { dst = append(dst, v) }\n }\n\n return dst\n },\n // find iterates over elements of `x`, returning value of the first element `fn`\n // returns truthy for. `fn` is invoked with two arguments: `key` and `value`.\n // `key` is an int index if `x` is array. `key` is a string key if `x` is map.\n // It returns undefined if `x` is not enumerable.\n find: func(x, fn) {\n if !is_enumerable(x) { return undefined }\n\n for k, v in x {\n if fn(k, v) { return v }\n }\n },\n // find_key iterates over elements of `x`, returning key or index of the first\n // element `fn` returns truthy for. `fn` is invoked with two arguments: `key`\n // and `value`. `key` is an int index if `x` is array. `key` is a string key if\n // `x` is map. It returns undefined if `x` is not enumerable.\n find_key: func(x, fn) {\n if !is_enumerable(x) { return undefined }\n\n for k, v in x {\n if fn(k, v) { return k }\n }\n },\n // map creates an array of values by running each element in `x` through `fn`.\n // `fn` is invoked with two arguments: `key` and `value`. `key` is an int index\n // if `x` is array. `key` is a string key if `x` is map. It returns undefined\n // if `x` is not enumerable.\n map: func(x, fn) {\n if !is_enumerable(x) { return undefined }\n\n dst := []\n for k, v in x {\n dst = append(dst, fn(k, v))\n }\n\n return dst\n },\n // key returns the first argument.\n key: func(k, _) { return k },\n // value returns the second argument.\n value: func(_, v) { return v }\n}\n",
|
||||
}
|
||||
|
||||
3
vendor/github.com/d5/tengo/v2/stdlib/srcmod_enum.tengo
generated
vendored
3
vendor/github.com/d5/tengo/v2/stdlib/srcmod_enum.tengo
generated
vendored
@@ -73,8 +73,7 @@ export {
|
||||
},
|
||||
// filter iterates over elements of `x`, returning an array of all elements `fn`
|
||||
// returns truthy for. `fn` is invoked with two arguments: `key` and `value`.
|
||||
// `key` is an int index if `x` is array. `key` is a string key if `x` is map.
|
||||
// It returns undefined if `x` is not enumerable.
|
||||
// `key` is an int index if `x` is array. It returns undefined if `x` is not array.
|
||||
filter: func(x, fn) {
|
||||
if !is_array_like(x) { return undefined }
|
||||
|
||||
|
||||
20
vendor/github.com/gomarkdown/markdown/README.md
generated
vendored
20
vendor/github.com/gomarkdown/markdown/README.md
generated
vendored
@@ -1,6 +1,6 @@
|
||||
# Markdown Parser and HTML Renderer for Go
|
||||
|
||||
[](https://godoc.org/github.com/gomarkdown/markdown) [](https://codecov.io/gh/gomarkdown/markdown)
|
||||
[](https://pkg.go.dev/badge/github.com/gomarkdown/markdown)
|
||||
|
||||
Package `github.com/gomarkdown/markdown` is a very fast Go library for parsing [Markdown](https://daringfireball.net/projects/markdown/) documents and rendering them to HTML.
|
||||
|
||||
@@ -8,10 +8,10 @@ It's fast and supports common extensions.
|
||||
|
||||
## API Docs:
|
||||
|
||||
- https://godoc.org/github.com/gomarkdown/markdown : top level package
|
||||
- https://godoc.org/github.com/gomarkdown/markdown/ast : defines abstract syntax tree of parsed markdown document
|
||||
- https://godoc.org/github.com/gomarkdown/markdown/parser : parser
|
||||
- https://godoc.org/github.com/gomarkdown/markdown/html : html renderer
|
||||
- https://pkg.go.dev/github.com/gomarkdown/markdown : top level package
|
||||
- https://pkg.go.dev/github.com/gomarkdown/markdown/ast : defines abstract syntax tree of parsed markdown document
|
||||
- https://pkg.go.dev/github.com/gomarkdown/markdown/parser : parser
|
||||
- https://pkg.go.dev/github.com/gomarkdown/markdown/html : html renderer
|
||||
|
||||
## Users
|
||||
|
||||
@@ -40,7 +40,7 @@ output := markdown.ToHTML(md, nil, nil)
|
||||
|
||||
Markdown format is loosely specified and there are multiple extensions invented after original specification was created.
|
||||
|
||||
The parser supports several [extensions](https://godoc.org/github.com/gomarkdown/markdown/parser#Extensions).
|
||||
The parser supports several [extensions](https://pkg.go.dev/github.com/gomarkdown/markdown/parser#Extensions).
|
||||
|
||||
Default parser uses most common `parser.CommonExtensions` but you can easily use parser with custom extension:
|
||||
|
||||
@@ -59,7 +59,7 @@ html := markdown.ToHTML(md, parser, nil)
|
||||
|
||||
## Customizing HTML renderer
|
||||
|
||||
Similarly, HTML renderer can be configured with different [options](https://godoc.org/github.com/gomarkdown/markdown/html#RendererOptions)
|
||||
Similarly, HTML renderer can be configured with different [options](https://pkg.go.dev/github.com/gomarkdown/markdown/html#RendererOptions)
|
||||
|
||||
Here's how to use a custom renderer:
|
||||
|
||||
@@ -77,9 +77,9 @@ md := []byte("markdown text")
|
||||
html := markdown.ToHTML(md, nil, renderer)
|
||||
```
|
||||
|
||||
HTML renderer also supports reusing most of the logic and overriding rendering of only specifc nodes.
|
||||
HTML renderer also supports reusing most of the logic and overriding rendering of only specific nodes.
|
||||
|
||||
You can provide [RenderNodeFunc](https://godoc.org/github.com/gomarkdown/markdown/html#RenderNodeFunc) in [RendererOptions](https://godoc.org/github.com/gomarkdown/markdown/html#RendererOptions).
|
||||
You can provide [RenderNodeFunc](https://pkg.go.dev/github.com/gomarkdown/markdown/html#RenderNodeFunc) in [RendererOptions](https://pkg.go.dev/github.com/gomarkdown/markdown/html#RendererOptions).
|
||||
|
||||
The function is called for each node in AST, you can implement custom rendering logic and tell HTML renderer to skip rendering this node.
|
||||
|
||||
@@ -134,7 +134,7 @@ html := bluemonday.UGCPolicy().SanitizeBytes(maybeUnsafeHTML)
|
||||
## Windows / Mac newlines
|
||||
|
||||
The library only supports Unix newlines. If you have markdown text with possibly
|
||||
Windows / Mac newlines, normalize newlines before caling this librar using
|
||||
Windows / Mac newlines, normalize newlines before calling this library using
|
||||
`d = markdown.NormalizeNewlines(d)`
|
||||
|
||||
## mdtohtml command-line tool
|
||||
|
||||
9
vendor/github.com/gomarkdown/markdown/parser/block.go
generated
vendored
9
vendor/github.com/gomarkdown/markdown/parser/block.go
generated
vendored
@@ -1412,6 +1412,13 @@ gatherlines:
|
||||
// is this a nested list item?
|
||||
case (p.uliPrefix(chunk) > 0 && !p.isHRule(chunk)) || p.oliPrefix(chunk) > 0 || p.dliPrefix(chunk) > 0:
|
||||
|
||||
// if indent is 4 or more spaces on unordered or ordered lists
|
||||
// we need to add leadingWhiteSpaces + 1 spaces in the beginning of the chunk
|
||||
if indentIndex >= 4 && p.dliPrefix(chunk) <= 0 {
|
||||
leadingWhiteSpaces := skipChar(chunk, 0, ' ')
|
||||
chunk = data[ line+indentIndex - (leadingWhiteSpaces + 1) : i]
|
||||
}
|
||||
|
||||
// to be a nested list, it must be indented more
|
||||
// if not, it is either a different kind of list
|
||||
// or the next item in the same list
|
||||
@@ -1484,7 +1491,7 @@ gatherlines:
|
||||
}
|
||||
|
||||
// add the line into the working buffer without prefix
|
||||
raw.Write(data[line+indentIndex : i])
|
||||
raw.Write(chunk)
|
||||
|
||||
line = i
|
||||
}
|
||||
|
||||
15
vendor/github.com/gomarkdown/markdown/parser/block_table.go
generated
vendored
15
vendor/github.com/gomarkdown/markdown/parser/block_table.go
generated
vendored
@@ -25,6 +25,11 @@ func (p *Parser) tableRow(data []byte, columns []ast.CellAlignFlags, header bool
|
||||
|
||||
cellStart := i
|
||||
|
||||
// If we are in a codespan we should discount any | we see, check for that here and skip ahead.
|
||||
if isCode, _ := codeSpan(p, data[i:], 0); isCode > 0 {
|
||||
i += isCode - 1
|
||||
}
|
||||
|
||||
for i < n && (data[i] != '|' || isBackslashEscaped(data, i)) && data[i] != '\n' {
|
||||
i++
|
||||
}
|
||||
@@ -84,6 +89,11 @@ func (p *Parser) tableFooter(data []byte) bool {
|
||||
n := len(data)
|
||||
i := skipCharN(data, 0, ' ', 3)
|
||||
for ; i < n && data[i] != '\n'; i++ {
|
||||
// If we are in a codespan we should discount any | we see, check for that here and skip ahead.
|
||||
if isCode, _ := codeSpan(p, data[i:], 0); isCode > 0 {
|
||||
i += isCode - 1
|
||||
}
|
||||
|
||||
if data[i] == '|' && !isBackslashEscaped(data, i) {
|
||||
colCount++
|
||||
continue
|
||||
@@ -111,6 +121,11 @@ func (p *Parser) tableHeader(data []byte, doRender bool) (size int, columns []as
|
||||
headerIsUnderline := true
|
||||
headerIsWithEmptyFields := true
|
||||
for i = 0; i < len(data) && data[i] != '\n'; i++ {
|
||||
// If we are in a codespan we should discount any | we see, check for that here and skip ahead.
|
||||
if isCode, _ := codeSpan(p, data[i:], 0); isCode > 0 {
|
||||
i += isCode - 1
|
||||
}
|
||||
|
||||
if data[i] == '|' && !isBackslashEscaped(data, i) {
|
||||
colCount++
|
||||
}
|
||||
|
||||
39
vendor/github.com/gorilla/websocket/README.md
generated
vendored
39
vendor/github.com/gorilla/websocket/README.md
generated
vendored
@@ -6,6 +6,13 @@
|
||||
Gorilla WebSocket is a [Go](http://golang.org/) implementation of the
|
||||
[WebSocket](http://www.rfc-editor.org/rfc/rfc6455.txt) protocol.
|
||||
|
||||
|
||||
---
|
||||
|
||||
⚠️ **[The Gorilla WebSocket Package is looking for a new maintainer](https://github.com/gorilla/websocket/issues/370)**
|
||||
|
||||
---
|
||||
|
||||
### Documentation
|
||||
|
||||
* [API Reference](https://pkg.go.dev/github.com/gorilla/websocket?tab=doc)
|
||||
@@ -30,35 +37,3 @@ The Gorilla WebSocket package passes the server tests in the [Autobahn Test
|
||||
Suite](https://github.com/crossbario/autobahn-testsuite) using the application in the [examples/autobahn
|
||||
subdirectory](https://github.com/gorilla/websocket/tree/master/examples/autobahn).
|
||||
|
||||
### Gorilla WebSocket compared with other packages
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th><a href="http://godoc.org/github.com/gorilla/websocket">github.com/gorilla</a></th>
|
||||
<th><a href="http://godoc.org/golang.org/x/net/websocket">golang.org/x/net</a></th>
|
||||
</tr>
|
||||
<tr>
|
||||
<tr><td colspan="3"><a href="http://tools.ietf.org/html/rfc6455">RFC 6455</a> Features</td></tr>
|
||||
<tr><td>Passes <a href="https://github.com/crossbario/autobahn-testsuite">Autobahn Test Suite</a></td><td><a href="https://github.com/gorilla/websocket/tree/master/examples/autobahn">Yes</a></td><td>No</td></tr>
|
||||
<tr><td>Receive <a href="https://tools.ietf.org/html/rfc6455#section-5.4">fragmented</a> message<td>Yes</td><td><a href="https://code.google.com/p/go/issues/detail?id=7632">No</a>, see note 1</td></tr>
|
||||
<tr><td>Send <a href="https://tools.ietf.org/html/rfc6455#section-5.5.1">close</a> message</td><td><a href="http://godoc.org/github.com/gorilla/websocket#hdr-Control_Messages">Yes</a></td><td><a href="https://code.google.com/p/go/issues/detail?id=4588">No</a></td></tr>
|
||||
<tr><td>Send <a href="https://tools.ietf.org/html/rfc6455#section-5.5.2">pings</a> and receive <a href="https://tools.ietf.org/html/rfc6455#section-5.5.3">pongs</a></td><td><a href="http://godoc.org/github.com/gorilla/websocket#hdr-Control_Messages">Yes</a></td><td>No</td></tr>
|
||||
<tr><td>Get the <a href="https://tools.ietf.org/html/rfc6455#section-5.6">type</a> of a received data message</td><td>Yes</td><td>Yes, see note 2</td></tr>
|
||||
<tr><td colspan="3">Other Features</tr></td>
|
||||
<tr><td><a href="https://tools.ietf.org/html/rfc7692">Compression Extensions</a></td><td>Experimental</td><td>No</td></tr>
|
||||
<tr><td>Read message using io.Reader</td><td><a href="http://godoc.org/github.com/gorilla/websocket#Conn.NextReader">Yes</a></td><td>No, see note 3</td></tr>
|
||||
<tr><td>Write message using io.WriteCloser</td><td><a href="http://godoc.org/github.com/gorilla/websocket#Conn.NextWriter">Yes</a></td><td>No, see note 3</td></tr>
|
||||
</table>
|
||||
|
||||
Notes:
|
||||
|
||||
1. Large messages are fragmented in [Chrome's new WebSocket implementation](http://www.ietf.org/mail-archive/web/hybi/current/msg10503.html).
|
||||
2. The application can get the type of a received data message by implementing
|
||||
a [Codec marshal](http://godoc.org/golang.org/x/net/websocket#Codec.Marshal)
|
||||
function.
|
||||
3. The go.net io.Reader and io.Writer operate across WebSocket frame boundaries.
|
||||
Read returns when the input buffer is full or a frame boundary is
|
||||
encountered. Each call to Write sends a single frame message. The Gorilla
|
||||
io.Reader and io.WriteCloser operate on a single WebSocket message.
|
||||
|
||||
|
||||
77
vendor/github.com/gorilla/websocket/client.go
generated
vendored
77
vendor/github.com/gorilla/websocket/client.go
generated
vendored
@@ -48,15 +48,23 @@ func NewClient(netConn net.Conn, u *url.URL, requestHeader http.Header, readBufS
|
||||
}
|
||||
|
||||
// A Dialer contains options for connecting to WebSocket server.
|
||||
//
|
||||
// It is safe to call Dialer's methods concurrently.
|
||||
type Dialer struct {
|
||||
// NetDial specifies the dial function for creating TCP connections. If
|
||||
// NetDial is nil, net.Dial is used.
|
||||
NetDial func(network, addr string) (net.Conn, error)
|
||||
|
||||
// NetDialContext specifies the dial function for creating TCP connections. If
|
||||
// NetDialContext is nil, net.DialContext is used.
|
||||
// NetDialContext is nil, NetDial is used.
|
||||
NetDialContext func(ctx context.Context, network, addr string) (net.Conn, error)
|
||||
|
||||
// NetDialTLSContext specifies the dial function for creating TLS/TCP connections. If
|
||||
// NetDialTLSContext is nil, NetDialContext is used.
|
||||
// If NetDialTLSContext is set, Dial assumes the TLS handshake is done there and
|
||||
// TLSClientConfig is ignored.
|
||||
NetDialTLSContext func(ctx context.Context, network, addr string) (net.Conn, error)
|
||||
|
||||
// Proxy specifies a function to return a proxy for a given
|
||||
// Request. If the function returns a non-nil error, the
|
||||
// request is aborted with the provided error.
|
||||
@@ -65,6 +73,8 @@ type Dialer struct {
|
||||
|
||||
// TLSClientConfig specifies the TLS configuration to use with tls.Client.
|
||||
// If nil, the default configuration is used.
|
||||
// If either NetDialTLS or NetDialTLSContext are set, Dial assumes the TLS handshake
|
||||
// is done there and TLSClientConfig is ignored.
|
||||
TLSClientConfig *tls.Config
|
||||
|
||||
// HandshakeTimeout specifies the duration for the handshake to complete.
|
||||
@@ -176,7 +186,7 @@ func (d *Dialer) DialContext(ctx context.Context, urlStr string, requestHeader h
|
||||
}
|
||||
|
||||
req := &http.Request{
|
||||
Method: "GET",
|
||||
Method: http.MethodGet,
|
||||
URL: u,
|
||||
Proto: "HTTP/1.1",
|
||||
ProtoMajor: 1,
|
||||
@@ -237,13 +247,32 @@ func (d *Dialer) DialContext(ctx context.Context, urlStr string, requestHeader h
|
||||
// Get network dial function.
|
||||
var netDial func(network, add string) (net.Conn, error)
|
||||
|
||||
if d.NetDialContext != nil {
|
||||
netDial = func(network, addr string) (net.Conn, error) {
|
||||
return d.NetDialContext(ctx, network, addr)
|
||||
switch u.Scheme {
|
||||
case "http":
|
||||
if d.NetDialContext != nil {
|
||||
netDial = func(network, addr string) (net.Conn, error) {
|
||||
return d.NetDialContext(ctx, network, addr)
|
||||
}
|
||||
} else if d.NetDial != nil {
|
||||
netDial = d.NetDial
|
||||
}
|
||||
} else if d.NetDial != nil {
|
||||
netDial = d.NetDial
|
||||
} else {
|
||||
case "https":
|
||||
if d.NetDialTLSContext != nil {
|
||||
netDial = func(network, addr string) (net.Conn, error) {
|
||||
return d.NetDialTLSContext(ctx, network, addr)
|
||||
}
|
||||
} else if d.NetDialContext != nil {
|
||||
netDial = func(network, addr string) (net.Conn, error) {
|
||||
return d.NetDialContext(ctx, network, addr)
|
||||
}
|
||||
} else if d.NetDial != nil {
|
||||
netDial = d.NetDial
|
||||
}
|
||||
default:
|
||||
return nil, nil, errMalformedURL
|
||||
}
|
||||
|
||||
if netDial == nil {
|
||||
netDialer := &net.Dialer{}
|
||||
netDial = func(network, addr string) (net.Conn, error) {
|
||||
return netDialer.DialContext(ctx, network, addr)
|
||||
@@ -304,7 +333,9 @@ func (d *Dialer) DialContext(ctx context.Context, urlStr string, requestHeader h
|
||||
}
|
||||
}()
|
||||
|
||||
if u.Scheme == "https" {
|
||||
if u.Scheme == "https" && d.NetDialTLSContext == nil {
|
||||
// If NetDialTLSContext is set, assume that the TLS handshake has already been done
|
||||
|
||||
cfg := cloneTLSConfig(d.TLSClientConfig)
|
||||
if cfg.ServerName == "" {
|
||||
cfg.ServerName = hostNoPort
|
||||
@@ -312,11 +343,12 @@ func (d *Dialer) DialContext(ctx context.Context, urlStr string, requestHeader h
|
||||
tlsConn := tls.Client(netConn, cfg)
|
||||
netConn = tlsConn
|
||||
|
||||
var err error
|
||||
if trace != nil {
|
||||
err = doHandshakeWithTrace(trace, tlsConn, cfg)
|
||||
} else {
|
||||
err = doHandshake(tlsConn, cfg)
|
||||
if trace != nil && trace.TLSHandshakeStart != nil {
|
||||
trace.TLSHandshakeStart()
|
||||
}
|
||||
err := doHandshake(ctx, tlsConn, cfg)
|
||||
if trace != nil && trace.TLSHandshakeDone != nil {
|
||||
trace.TLSHandshakeDone(tlsConn.ConnectionState(), err)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
@@ -348,8 +380,8 @@ func (d *Dialer) DialContext(ctx context.Context, urlStr string, requestHeader h
|
||||
}
|
||||
|
||||
if resp.StatusCode != 101 ||
|
||||
!strings.EqualFold(resp.Header.Get("Upgrade"), "websocket") ||
|
||||
!strings.EqualFold(resp.Header.Get("Connection"), "upgrade") ||
|
||||
!tokenListContainsValue(resp.Header, "Upgrade", "websocket") ||
|
||||
!tokenListContainsValue(resp.Header, "Connection", "upgrade") ||
|
||||
resp.Header.Get("Sec-Websocket-Accept") != computeAcceptKey(challengeKey) {
|
||||
// Before closing the network connection on return from this
|
||||
// function, slurp up some of the response to aid application
|
||||
@@ -382,14 +414,9 @@ func (d *Dialer) DialContext(ctx context.Context, urlStr string, requestHeader h
|
||||
return conn, resp, nil
|
||||
}
|
||||
|
||||
func doHandshake(tlsConn *tls.Conn, cfg *tls.Config) error {
|
||||
if err := tlsConn.Handshake(); err != nil {
|
||||
return err
|
||||
func cloneTLSConfig(cfg *tls.Config) *tls.Config {
|
||||
if cfg == nil {
|
||||
return &tls.Config{}
|
||||
}
|
||||
if !cfg.InsecureSkipVerify {
|
||||
if err := tlsConn.VerifyHostname(cfg.ServerName); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
return cfg.Clone()
|
||||
}
|
||||
|
||||
16
vendor/github.com/gorilla/websocket/client_clone.go
generated
vendored
16
vendor/github.com/gorilla/websocket/client_clone.go
generated
vendored
@@ -1,16 +0,0 @@
|
||||
// Copyright 2013 The Gorilla WebSocket Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build go1.8
|
||||
|
||||
package websocket
|
||||
|
||||
import "crypto/tls"
|
||||
|
||||
func cloneTLSConfig(cfg *tls.Config) *tls.Config {
|
||||
if cfg == nil {
|
||||
return &tls.Config{}
|
||||
}
|
||||
return cfg.Clone()
|
||||
}
|
||||
38
vendor/github.com/gorilla/websocket/client_clone_legacy.go
generated
vendored
38
vendor/github.com/gorilla/websocket/client_clone_legacy.go
generated
vendored
@@ -1,38 +0,0 @@
|
||||
// Copyright 2013 The Gorilla WebSocket Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !go1.8
|
||||
|
||||
package websocket
|
||||
|
||||
import "crypto/tls"
|
||||
|
||||
// cloneTLSConfig clones all public fields except the fields
|
||||
// SessionTicketsDisabled and SessionTicketKey. This avoids copying the
|
||||
// sync.Mutex in the sync.Once and makes it safe to call cloneTLSConfig on a
|
||||
// config in active use.
|
||||
func cloneTLSConfig(cfg *tls.Config) *tls.Config {
|
||||
if cfg == nil {
|
||||
return &tls.Config{}
|
||||
}
|
||||
return &tls.Config{
|
||||
Rand: cfg.Rand,
|
||||
Time: cfg.Time,
|
||||
Certificates: cfg.Certificates,
|
||||
NameToCertificate: cfg.NameToCertificate,
|
||||
GetCertificate: cfg.GetCertificate,
|
||||
RootCAs: cfg.RootCAs,
|
||||
NextProtos: cfg.NextProtos,
|
||||
ServerName: cfg.ServerName,
|
||||
ClientAuth: cfg.ClientAuth,
|
||||
ClientCAs: cfg.ClientCAs,
|
||||
InsecureSkipVerify: cfg.InsecureSkipVerify,
|
||||
CipherSuites: cfg.CipherSuites,
|
||||
PreferServerCipherSuites: cfg.PreferServerCipherSuites,
|
||||
ClientSessionCache: cfg.ClientSessionCache,
|
||||
MinVersion: cfg.MinVersion,
|
||||
MaxVersion: cfg.MaxVersion,
|
||||
CurvePreferences: cfg.CurvePreferences,
|
||||
}
|
||||
}
|
||||
63
vendor/github.com/gorilla/websocket/conn.go
generated
vendored
63
vendor/github.com/gorilla/websocket/conn.go
generated
vendored
@@ -13,6 +13,7 @@ import (
|
||||
"math/rand"
|
||||
"net"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
"unicode/utf8"
|
||||
@@ -401,6 +402,12 @@ func (c *Conn) write(frameType int, deadline time.Time, buf0, buf1 []byte) error
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Conn) writeBufs(bufs ...[]byte) error {
|
||||
b := net.Buffers(bufs)
|
||||
_, err := b.WriteTo(c.conn)
|
||||
return err
|
||||
}
|
||||
|
||||
// WriteControl writes a control message with the given deadline. The allowed
|
||||
// message types are CloseMessage, PingMessage and PongMessage.
|
||||
func (c *Conn) WriteControl(messageType int, data []byte, deadline time.Time) error {
|
||||
@@ -794,47 +801,69 @@ func (c *Conn) advanceFrame() (int, error) {
|
||||
}
|
||||
|
||||
// 2. Read and parse first two bytes of frame header.
|
||||
// To aid debugging, collect and report all errors in the first two bytes
|
||||
// of the header.
|
||||
|
||||
var errors []string
|
||||
|
||||
p, err := c.read(2)
|
||||
if err != nil {
|
||||
return noFrame, err
|
||||
}
|
||||
|
||||
final := p[0]&finalBit != 0
|
||||
frameType := int(p[0] & 0xf)
|
||||
final := p[0]&finalBit != 0
|
||||
rsv1 := p[0]&rsv1Bit != 0
|
||||
rsv2 := p[0]&rsv2Bit != 0
|
||||
rsv3 := p[0]&rsv3Bit != 0
|
||||
mask := p[1]&maskBit != 0
|
||||
c.setReadRemaining(int64(p[1] & 0x7f))
|
||||
|
||||
c.readDecompress = false
|
||||
if c.newDecompressionReader != nil && (p[0]&rsv1Bit) != 0 {
|
||||
c.readDecompress = true
|
||||
p[0] &^= rsv1Bit
|
||||
if rsv1 {
|
||||
if c.newDecompressionReader != nil {
|
||||
c.readDecompress = true
|
||||
} else {
|
||||
errors = append(errors, "RSV1 set")
|
||||
}
|
||||
}
|
||||
|
||||
if rsv := p[0] & (rsv1Bit | rsv2Bit | rsv3Bit); rsv != 0 {
|
||||
return noFrame, c.handleProtocolError("unexpected reserved bits 0x" + strconv.FormatInt(int64(rsv), 16))
|
||||
if rsv2 {
|
||||
errors = append(errors, "RSV2 set")
|
||||
}
|
||||
|
||||
if rsv3 {
|
||||
errors = append(errors, "RSV3 set")
|
||||
}
|
||||
|
||||
switch frameType {
|
||||
case CloseMessage, PingMessage, PongMessage:
|
||||
if c.readRemaining > maxControlFramePayloadSize {
|
||||
return noFrame, c.handleProtocolError("control frame length > 125")
|
||||
errors = append(errors, "len > 125 for control")
|
||||
}
|
||||
if !final {
|
||||
return noFrame, c.handleProtocolError("control frame not final")
|
||||
errors = append(errors, "FIN not set on control")
|
||||
}
|
||||
case TextMessage, BinaryMessage:
|
||||
if !c.readFinal {
|
||||
return noFrame, c.handleProtocolError("message start before final message frame")
|
||||
errors = append(errors, "data before FIN")
|
||||
}
|
||||
c.readFinal = final
|
||||
case continuationFrame:
|
||||
if c.readFinal {
|
||||
return noFrame, c.handleProtocolError("continuation after final message frame")
|
||||
errors = append(errors, "continuation after FIN")
|
||||
}
|
||||
c.readFinal = final
|
||||
default:
|
||||
return noFrame, c.handleProtocolError("unknown opcode " + strconv.Itoa(frameType))
|
||||
errors = append(errors, "bad opcode "+strconv.Itoa(frameType))
|
||||
}
|
||||
|
||||
if mask != c.isServer {
|
||||
errors = append(errors, "bad MASK")
|
||||
}
|
||||
|
||||
if len(errors) > 0 {
|
||||
return noFrame, c.handleProtocolError(strings.Join(errors, ", "))
|
||||
}
|
||||
|
||||
// 3. Read and parse frame length as per
|
||||
@@ -872,10 +901,6 @@ func (c *Conn) advanceFrame() (int, error) {
|
||||
|
||||
// 4. Handle frame masking.
|
||||
|
||||
if mask != c.isServer {
|
||||
return noFrame, c.handleProtocolError("incorrect mask flag")
|
||||
}
|
||||
|
||||
if mask {
|
||||
c.readMaskPos = 0
|
||||
p, err := c.read(len(c.readMaskKey))
|
||||
@@ -935,7 +960,7 @@ func (c *Conn) advanceFrame() (int, error) {
|
||||
if len(payload) >= 2 {
|
||||
closeCode = int(binary.BigEndian.Uint16(payload))
|
||||
if !isValidReceivedCloseCode(closeCode) {
|
||||
return noFrame, c.handleProtocolError("invalid close code")
|
||||
return noFrame, c.handleProtocolError("bad close code " + strconv.Itoa(closeCode))
|
||||
}
|
||||
closeText = string(payload[2:])
|
||||
if !utf8.ValidString(closeText) {
|
||||
@@ -952,7 +977,11 @@ func (c *Conn) advanceFrame() (int, error) {
|
||||
}
|
||||
|
||||
func (c *Conn) handleProtocolError(message string) error {
|
||||
c.WriteControl(CloseMessage, FormatCloseMessage(CloseProtocolError, message), time.Now().Add(writeWait))
|
||||
data := FormatCloseMessage(CloseProtocolError, message)
|
||||
if len(data) > maxControlFramePayloadSize {
|
||||
data = data[:maxControlFramePayloadSize]
|
||||
}
|
||||
c.WriteControl(CloseMessage, data, time.Now().Add(writeWait))
|
||||
return errors.New("websocket: " + message)
|
||||
}
|
||||
|
||||
|
||||
15
vendor/github.com/gorilla/websocket/conn_write.go
generated
vendored
15
vendor/github.com/gorilla/websocket/conn_write.go
generated
vendored
@@ -1,15 +0,0 @@
|
||||
// Copyright 2016 The Gorilla WebSocket Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build go1.8
|
||||
|
||||
package websocket
|
||||
|
||||
import "net"
|
||||
|
||||
func (c *Conn) writeBufs(bufs ...[]byte) error {
|
||||
b := net.Buffers(bufs)
|
||||
_, err := b.WriteTo(c.conn)
|
||||
return err
|
||||
}
|
||||
18
vendor/github.com/gorilla/websocket/conn_write_legacy.go
generated
vendored
18
vendor/github.com/gorilla/websocket/conn_write_legacy.go
generated
vendored
@@ -1,18 +0,0 @@
|
||||
// Copyright 2016 The Gorilla WebSocket Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !go1.8
|
||||
|
||||
package websocket
|
||||
|
||||
func (c *Conn) writeBufs(bufs ...[]byte) error {
|
||||
for _, buf := range bufs {
|
||||
if len(buf) > 0 {
|
||||
if _, err := c.conn.Write(buf); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
1
vendor/github.com/gorilla/websocket/mask.go
generated
vendored
1
vendor/github.com/gorilla/websocket/mask.go
generated
vendored
@@ -2,6 +2,7 @@
|
||||
// this source code is governed by a BSD-style license that can be found in the
|
||||
// LICENSE file.
|
||||
|
||||
//go:build !appengine
|
||||
// +build !appengine
|
||||
|
||||
package websocket
|
||||
|
||||
1
vendor/github.com/gorilla/websocket/mask_safe.go
generated
vendored
1
vendor/github.com/gorilla/websocket/mask_safe.go
generated
vendored
@@ -2,6 +2,7 @@
|
||||
// this source code is governed by a BSD-style license that can be found in the
|
||||
// LICENSE file.
|
||||
|
||||
//go:build appengine
|
||||
// +build appengine
|
||||
|
||||
package websocket
|
||||
|
||||
2
vendor/github.com/gorilla/websocket/proxy.go
generated
vendored
2
vendor/github.com/gorilla/websocket/proxy.go
generated
vendored
@@ -48,7 +48,7 @@ func (hpd *httpProxyDialer) Dial(network string, addr string) (net.Conn, error)
|
||||
}
|
||||
|
||||
connectReq := &http.Request{
|
||||
Method: "CONNECT",
|
||||
Method: http.MethodConnect,
|
||||
URL: &url.URL{Opaque: addr},
|
||||
Host: addr,
|
||||
Header: connectHeader,
|
||||
|
||||
8
vendor/github.com/gorilla/websocket/server.go
generated
vendored
8
vendor/github.com/gorilla/websocket/server.go
generated
vendored
@@ -23,6 +23,8 @@ func (e HandshakeError) Error() string { return e.message }
|
||||
|
||||
// Upgrader specifies parameters for upgrading an HTTP connection to a
|
||||
// WebSocket connection.
|
||||
//
|
||||
// It is safe to call Upgrader's methods concurrently.
|
||||
type Upgrader struct {
|
||||
// HandshakeTimeout specifies the duration for the handshake to complete.
|
||||
HandshakeTimeout time.Duration
|
||||
@@ -115,8 +117,8 @@ func (u *Upgrader) selectSubprotocol(r *http.Request, responseHeader http.Header
|
||||
// Upgrade upgrades the HTTP server connection to the WebSocket protocol.
|
||||
//
|
||||
// The responseHeader is included in the response to the client's upgrade
|
||||
// request. Use the responseHeader to specify cookies (Set-Cookie) and the
|
||||
// application negotiated subprotocol (Sec-WebSocket-Protocol).
|
||||
// request. Use the responseHeader to specify cookies (Set-Cookie). To specify
|
||||
// subprotocols supported by the server, set Upgrader.Subprotocols directly.
|
||||
//
|
||||
// If the upgrade fails, then Upgrade replies to the client with an HTTP error
|
||||
// response.
|
||||
@@ -131,7 +133,7 @@ func (u *Upgrader) Upgrade(w http.ResponseWriter, r *http.Request, responseHeade
|
||||
return u.returnError(w, r, http.StatusBadRequest, badHandshake+"'websocket' token not found in 'Upgrade' header")
|
||||
}
|
||||
|
||||
if r.Method != "GET" {
|
||||
if r.Method != http.MethodGet {
|
||||
return u.returnError(w, r, http.StatusMethodNotAllowed, badHandshake+"request method is not GET")
|
||||
}
|
||||
|
||||
|
||||
21
vendor/github.com/gorilla/websocket/tls_handshake.go
generated
vendored
Normal file
21
vendor/github.com/gorilla/websocket/tls_handshake.go
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
//go:build go1.17
|
||||
// +build go1.17
|
||||
|
||||
package websocket
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
)
|
||||
|
||||
func doHandshake(ctx context.Context, tlsConn *tls.Conn, cfg *tls.Config) error {
|
||||
if err := tlsConn.HandshakeContext(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if !cfg.InsecureSkipVerify {
|
||||
if err := tlsConn.VerifyHostname(cfg.ServerName); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
21
vendor/github.com/gorilla/websocket/tls_handshake_116.go
generated
vendored
Normal file
21
vendor/github.com/gorilla/websocket/tls_handshake_116.go
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
//go:build !go1.17
|
||||
// +build !go1.17
|
||||
|
||||
package websocket
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
)
|
||||
|
||||
func doHandshake(ctx context.Context, tlsConn *tls.Conn, cfg *tls.Config) error {
|
||||
if err := tlsConn.Handshake(); err != nil {
|
||||
return err
|
||||
}
|
||||
if !cfg.InsecureSkipVerify {
|
||||
if err := tlsConn.VerifyHostname(cfg.ServerName); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
19
vendor/github.com/gorilla/websocket/trace.go
generated
vendored
19
vendor/github.com/gorilla/websocket/trace.go
generated
vendored
@@ -1,19 +0,0 @@
|
||||
// +build go1.8
|
||||
|
||||
package websocket
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"net/http/httptrace"
|
||||
)
|
||||
|
||||
func doHandshakeWithTrace(trace *httptrace.ClientTrace, tlsConn *tls.Conn, cfg *tls.Config) error {
|
||||
if trace.TLSHandshakeStart != nil {
|
||||
trace.TLSHandshakeStart()
|
||||
}
|
||||
err := doHandshake(tlsConn, cfg)
|
||||
if trace.TLSHandshakeDone != nil {
|
||||
trace.TLSHandshakeDone(tlsConn.ConnectionState(), err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
12
vendor/github.com/gorilla/websocket/trace_17.go
generated
vendored
12
vendor/github.com/gorilla/websocket/trace_17.go
generated
vendored
@@ -1,12 +0,0 @@
|
||||
// +build !go1.8
|
||||
|
||||
package websocket
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"net/http/httptrace"
|
||||
)
|
||||
|
||||
func doHandshakeWithTrace(trace *httptrace.ClientTrace, tlsConn *tls.Conn, cfg *tls.Config) error {
|
||||
return doHandshake(tlsConn, cfg)
|
||||
}
|
||||
3
vendor/github.com/harmony-development/shibshib/gen/chat/v1/chat_hrpc_client.pb.go
generated
vendored
3
vendor/github.com/harmony-development/shibshib/gen/chat/v1/chat_hrpc_client.pb.go
generated
vendored
@@ -156,6 +156,9 @@ type ChatServiceClient interface {
|
||||
// Endpoint to unpin a message in a guild channel.
|
||||
UnpinMessage(context.Context, *UnpinMessageRequest) (*UnpinMessageResponse, error)
|
||||
// Endpoint to stream events from the homeserver.
|
||||
// By default, this endpoint will subscribe to all events.
|
||||
// Any guilds joined in the future will be added to the subscription as well.
|
||||
// Use the UnsubscribeFromAll event for unsubscribing from all current subscriptions and disable the automatic guild subscriptions
|
||||
StreamEvents(context.Context, chan *StreamEventsRequest) (chan *StreamEventsResponse, error)
|
||||
// Endpoint to add a reaction to a message.
|
||||
AddReaction(context.Context, *AddReactionRequest) (*AddReactionResponse, error)
|
||||
|
||||
1154
vendor/github.com/harmony-development/shibshib/gen/chat/v1/guilds.pb.go
generated
vendored
1154
vendor/github.com/harmony-development/shibshib/gen/chat/v1/guilds.pb.go
generated
vendored
File diff suppressed because it is too large
Load Diff
1338
vendor/github.com/harmony-development/shibshib/gen/chat/v1/stream.pb.go
generated
vendored
1338
vendor/github.com/harmony-development/shibshib/gen/chat/v1/stream.pb.go
generated
vendored
File diff suppressed because it is too large
Load Diff
400
vendor/github.com/harmony-development/shibshib/gen/profile/v1/appdata.pb.go
generated
vendored
Normal file
400
vendor/github.com/harmony-development/shibshib/gen/profile/v1/appdata.pb.go
generated
vendored
Normal file
@@ -0,0 +1,400 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.23.0
|
||||
// protoc v3.17.3
|
||||
// source: profile/v1/appdata.proto
|
||||
|
||||
package profilev1
|
||||
|
||||
import (
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
v1 "github.com/harmony-development/shibshib/gen/harmonytypes/v1"
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
)
|
||||
|
||||
const (
|
||||
// Verify that this generated code is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
// This is a compile-time assertion that a sufficiently up-to-date version
|
||||
// of the legacy proto package is being used.
|
||||
const _ = proto.ProtoPackageIsVersion4
|
||||
|
||||
// A tag for an override. This is used as a
|
||||
// standard shorthand for sending a message with
|
||||
// an override. If a message starts with before and
|
||||
// ends with after, clients should send a message
|
||||
// with the override the tag belongs to, stripping
|
||||
// the tag indicators.
|
||||
type OverrideTag struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
// The portion of the tag before the messge.
|
||||
Before string `protobuf:"bytes,1,opt,name=before,proto3" json:"before,omitempty"`
|
||||
// The portion of the tag after the messge.
|
||||
After string `protobuf:"bytes,2,opt,name=after,proto3" json:"after,omitempty"`
|
||||
}
|
||||
|
||||
func (x *OverrideTag) Reset() {
|
||||
*x = OverrideTag{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_profile_v1_appdata_proto_msgTypes[0]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *OverrideTag) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*OverrideTag) ProtoMessage() {}
|
||||
|
||||
func (x *OverrideTag) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_profile_v1_appdata_proto_msgTypes[0]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use OverrideTag.ProtoReflect.Descriptor instead.
|
||||
func (*OverrideTag) Descriptor() ([]byte, []int) {
|
||||
return file_profile_v1_appdata_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
func (x *OverrideTag) GetBefore() string {
|
||||
if x != nil {
|
||||
return x.Before
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *OverrideTag) GetAfter() string {
|
||||
if x != nil {
|
||||
return x.After
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// An individual override
|
||||
type ProfileOverride struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
// The username for this override
|
||||
Username *string `protobuf:"bytes,1,opt,name=username,proto3,oneof" json:"username,omitempty"`
|
||||
// The avatar for this override
|
||||
Avatar *string `protobuf:"bytes,2,opt,name=avatar,proto3,oneof" json:"avatar,omitempty"`
|
||||
// The tags for this override.
|
||||
Tags []*OverrideTag `protobuf:"bytes,3,rep,name=tags,proto3" json:"tags,omitempty"`
|
||||
// The reason this override is used
|
||||
//
|
||||
// Types that are assignable to Reason:
|
||||
// *ProfileOverride_UserDefined
|
||||
// *ProfileOverride_SystemPlurality
|
||||
Reason isProfileOverride_Reason `protobuf_oneof:"reason"`
|
||||
}
|
||||
|
||||
func (x *ProfileOverride) Reset() {
|
||||
*x = ProfileOverride{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_profile_v1_appdata_proto_msgTypes[1]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *ProfileOverride) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*ProfileOverride) ProtoMessage() {}
|
||||
|
||||
func (x *ProfileOverride) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_profile_v1_appdata_proto_msgTypes[1]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use ProfileOverride.ProtoReflect.Descriptor instead.
|
||||
func (*ProfileOverride) Descriptor() ([]byte, []int) {
|
||||
return file_profile_v1_appdata_proto_rawDescGZIP(), []int{1}
|
||||
}
|
||||
|
||||
func (x *ProfileOverride) GetUsername() string {
|
||||
if x != nil && x.Username != nil {
|
||||
return *x.Username
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *ProfileOverride) GetAvatar() string {
|
||||
if x != nil && x.Avatar != nil {
|
||||
return *x.Avatar
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *ProfileOverride) GetTags() []*OverrideTag {
|
||||
if x != nil {
|
||||
return x.Tags
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *ProfileOverride) GetReason() isProfileOverride_Reason {
|
||||
if m != nil {
|
||||
return m.Reason
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *ProfileOverride) GetUserDefined() string {
|
||||
if x, ok := x.GetReason().(*ProfileOverride_UserDefined); ok {
|
||||
return x.UserDefined
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *ProfileOverride) GetSystemPlurality() *v1.Empty {
|
||||
if x, ok := x.GetReason().(*ProfileOverride_SystemPlurality); ok {
|
||||
return x.SystemPlurality
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type isProfileOverride_Reason interface {
|
||||
isProfileOverride_Reason()
|
||||
}
|
||||
|
||||
type ProfileOverride_UserDefined struct {
|
||||
// a custom reason in case the builtin ones don't fit
|
||||
UserDefined string `protobuf:"bytes,4,opt,name=user_defined,json=userDefined,proto3,oneof"`
|
||||
}
|
||||
|
||||
type ProfileOverride_SystemPlurality struct {
|
||||
// plurality, not system as in computer
|
||||
SystemPlurality *v1.Empty `protobuf:"bytes,5,opt,name=system_plurality,json=systemPlurality,proto3,oneof"`
|
||||
}
|
||||
|
||||
func (*ProfileOverride_UserDefined) isProfileOverride_Reason() {}
|
||||
|
||||
func (*ProfileOverride_SystemPlurality) isProfileOverride_Reason() {}
|
||||
|
||||
// The message used for the 'h.overrides' key
|
||||
// of appdata.
|
||||
type AppDataOverrides struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
// The list of overrides.
|
||||
Overrides []*ProfileOverride `protobuf:"bytes,1,rep,name=overrides,proto3" json:"overrides,omitempty"`
|
||||
}
|
||||
|
||||
func (x *AppDataOverrides) Reset() {
|
||||
*x = AppDataOverrides{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_profile_v1_appdata_proto_msgTypes[2]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *AppDataOverrides) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*AppDataOverrides) ProtoMessage() {}
|
||||
|
||||
func (x *AppDataOverrides) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_profile_v1_appdata_proto_msgTypes[2]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use AppDataOverrides.ProtoReflect.Descriptor instead.
|
||||
func (*AppDataOverrides) Descriptor() ([]byte, []int) {
|
||||
return file_profile_v1_appdata_proto_rawDescGZIP(), []int{2}
|
||||
}
|
||||
|
||||
func (x *AppDataOverrides) GetOverrides() []*ProfileOverride {
|
||||
if x != nil {
|
||||
return x.Overrides
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var File_profile_v1_appdata_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_profile_v1_appdata_proto_rawDesc = []byte{
|
||||
0x0a, 0x18, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x70, 0x70,
|
||||
0x64, 0x61, 0x74, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x13, 0x70, 0x72, 0x6f, 0x74,
|
||||
0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x1a,
|
||||
0x1b, 0x68, 0x61, 0x72, 0x6d, 0x6f, 0x6e, 0x79, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x76, 0x31,
|
||||
0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x3b, 0x0a, 0x0b,
|
||||
0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x54, 0x61, 0x67, 0x12, 0x16, 0x0a, 0x06, 0x62,
|
||||
0x65, 0x66, 0x6f, 0x72, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x62, 0x65, 0x66,
|
||||
0x6f, 0x72, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x61, 0x66, 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01,
|
||||
0x28, 0x09, 0x52, 0x05, 0x61, 0x66, 0x74, 0x65, 0x72, 0x22, 0x9a, 0x02, 0x0a, 0x0f, 0x50, 0x72,
|
||||
0x6f, 0x66, 0x69, 0x6c, 0x65, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x1f, 0x0a,
|
||||
0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48,
|
||||
0x01, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x88, 0x01, 0x01, 0x12, 0x1b,
|
||||
0x0a, 0x06, 0x61, 0x76, 0x61, 0x74, 0x61, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x02,
|
||||
0x52, 0x06, 0x61, 0x76, 0x61, 0x74, 0x61, 0x72, 0x88, 0x01, 0x01, 0x12, 0x34, 0x0a, 0x04, 0x74,
|
||||
0x61, 0x67, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x70, 0x72, 0x6f, 0x74,
|
||||
0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e,
|
||||
0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x54, 0x61, 0x67, 0x52, 0x04, 0x74, 0x61, 0x67,
|
||||
0x73, 0x12, 0x23, 0x0a, 0x0c, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65,
|
||||
0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0b, 0x75, 0x73, 0x65, 0x72, 0x44,
|
||||
0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x12, 0x4c, 0x0a, 0x10, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d,
|
||||
0x5f, 0x70, 0x6c, 0x75, 0x72, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b,
|
||||
0x32, 0x1f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x68, 0x61, 0x72, 0x6d,
|
||||
0x6f, 0x6e, 0x79, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6d, 0x70, 0x74,
|
||||
0x79, 0x48, 0x00, 0x52, 0x0f, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x50, 0x6c, 0x75, 0x72, 0x61,
|
||||
0x6c, 0x69, 0x74, 0x79, 0x42, 0x08, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x42, 0x0b,
|
||||
0x0a, 0x09, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x42, 0x09, 0x0a, 0x07, 0x5f,
|
||||
0x61, 0x76, 0x61, 0x74, 0x61, 0x72, 0x22, 0x56, 0x0a, 0x10, 0x41, 0x70, 0x70, 0x44, 0x61, 0x74,
|
||||
0x61, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x12, 0x42, 0x0a, 0x09, 0x6f, 0x76,
|
||||
0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e,
|
||||
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65,
|
||||
0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x4f, 0x76, 0x65, 0x72, 0x72,
|
||||
0x69, 0x64, 0x65, 0x52, 0x09, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x42, 0xd7,
|
||||
0x01, 0x0a, 0x17, 0x63, 0x6f, 0x6d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e,
|
||||
0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x42, 0x0c, 0x41, 0x70, 0x70, 0x64,
|
||||
0x61, 0x74, 0x61, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x40, 0x67, 0x69, 0x74, 0x68,
|
||||
0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x72, 0x6d, 0x6f, 0x6e, 0x79, 0x2d, 0x64,
|
||||
0x65, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x6d, 0x65, 0x6e, 0x74, 0x2f, 0x73, 0x68, 0x69, 0x62, 0x73,
|
||||
0x68, 0x69, 0x62, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x2f,
|
||||
0x76, 0x31, 0x3b, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x50,
|
||||
0x50, 0x58, 0xaa, 0x02, 0x13, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x50, 0x72,
|
||||
0x6f, 0x66, 0x69, 0x6c, 0x65, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x13, 0x50, 0x72, 0x6f, 0x74, 0x6f,
|
||||
0x63, 0x6f, 0x6c, 0x5c, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x5c, 0x56, 0x31, 0xe2, 0x02,
|
||||
0x1f, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x5c, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c,
|
||||
0x65, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61,
|
||||
0xea, 0x02, 0x15, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x3a, 0x3a, 0x50, 0x72, 0x6f,
|
||||
0x66, 0x69, 0x6c, 0x65, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
file_profile_v1_appdata_proto_rawDescOnce sync.Once
|
||||
file_profile_v1_appdata_proto_rawDescData = file_profile_v1_appdata_proto_rawDesc
|
||||
)
|
||||
|
||||
func file_profile_v1_appdata_proto_rawDescGZIP() []byte {
|
||||
file_profile_v1_appdata_proto_rawDescOnce.Do(func() {
|
||||
file_profile_v1_appdata_proto_rawDescData = protoimpl.X.CompressGZIP(file_profile_v1_appdata_proto_rawDescData)
|
||||
})
|
||||
return file_profile_v1_appdata_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_profile_v1_appdata_proto_msgTypes = make([]protoimpl.MessageInfo, 3)
|
||||
var file_profile_v1_appdata_proto_goTypes = []interface{}{
|
||||
(*OverrideTag)(nil), // 0: protocol.profile.v1.OverrideTag
|
||||
(*ProfileOverride)(nil), // 1: protocol.profile.v1.ProfileOverride
|
||||
(*AppDataOverrides)(nil), // 2: protocol.profile.v1.AppDataOverrides
|
||||
(*v1.Empty)(nil), // 3: protocol.harmonytypes.v1.Empty
|
||||
}
|
||||
var file_profile_v1_appdata_proto_depIdxs = []int32{
|
||||
0, // 0: protocol.profile.v1.ProfileOverride.tags:type_name -> protocol.profile.v1.OverrideTag
|
||||
3, // 1: protocol.profile.v1.ProfileOverride.system_plurality:type_name -> protocol.harmonytypes.v1.Empty
|
||||
1, // 2: protocol.profile.v1.AppDataOverrides.overrides:type_name -> protocol.profile.v1.ProfileOverride
|
||||
3, // [3:3] is the sub-list for method output_type
|
||||
3, // [3:3] is the sub-list for method input_type
|
||||
3, // [3:3] is the sub-list for extension type_name
|
||||
3, // [3:3] is the sub-list for extension extendee
|
||||
0, // [0:3] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_profile_v1_appdata_proto_init() }
|
||||
func file_profile_v1_appdata_proto_init() {
|
||||
if File_profile_v1_appdata_proto != nil {
|
||||
return
|
||||
}
|
||||
if !protoimpl.UnsafeEnabled {
|
||||
file_profile_v1_appdata_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*OverrideTag); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_profile_v1_appdata_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*ProfileOverride); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_profile_v1_appdata_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*AppDataOverrides); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
file_profile_v1_appdata_proto_msgTypes[1].OneofWrappers = []interface{}{
|
||||
(*ProfileOverride_UserDefined)(nil),
|
||||
(*ProfileOverride_SystemPlurality)(nil),
|
||||
}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: file_profile_v1_appdata_proto_rawDesc,
|
||||
NumEnums: 0,
|
||||
NumMessages: 3,
|
||||
NumExtensions: 0,
|
||||
NumServices: 0,
|
||||
},
|
||||
GoTypes: file_profile_v1_appdata_proto_goTypes,
|
||||
DependencyIndexes: file_profile_v1_appdata_proto_depIdxs,
|
||||
MessageInfos: file_profile_v1_appdata_proto_msgTypes,
|
||||
}.Build()
|
||||
File_profile_v1_appdata_proto = out.File
|
||||
file_profile_v1_appdata_proto_rawDesc = nil
|
||||
file_profile_v1_appdata_proto_goTypes = nil
|
||||
file_profile_v1_appdata_proto_depIdxs = nil
|
||||
}
|
||||
1397
vendor/github.com/kyokomi/emoji/v2/emoji_codemap.go
generated
vendored
1397
vendor/github.com/kyokomi/emoji/v2/emoji_codemap.go
generated
vendored
File diff suppressed because it is too large
Load Diff
21
vendor/github.com/labstack/echo/v4/CHANGELOG.md
generated
vendored
21
vendor/github.com/labstack/echo/v4/CHANGELOG.md
generated
vendored
@@ -1,5 +1,26 @@
|
||||
# Changelog
|
||||
|
||||
## v4.7.0 - 2022-03-01
|
||||
|
||||
**Enhancements**
|
||||
|
||||
* Add JWT, KeyAuth, CSRF multivalue extractors [#2060](https://github.com/labstack/echo/pull/2060)
|
||||
* Add LogErrorFunc to recover middleware [#2072](https://github.com/labstack/echo/pull/2072)
|
||||
* Add support for HEAD method query params binding [#2027](https://github.com/labstack/echo/pull/2027)
|
||||
* Improve filesystem support with echo.FileFS, echo.StaticFS, group.FileFS, group.StaticFS [#2064](https://github.com/labstack/echo/pull/2064)
|
||||
|
||||
**Fixes**
|
||||
|
||||
* Fix X-Real-IP bug, improve tests [#2007](https://github.com/labstack/echo/pull/2007)
|
||||
* Minor syntax fixes [#1994](https://github.com/labstack/echo/pull/1994), [#2102](https://github.com/labstack/echo/pull/2102), [#2102](https://github.com/labstack/echo/pull/2102)
|
||||
|
||||
**General**
|
||||
|
||||
* Add cache-control and connection headers [#2103](https://github.com/labstack/echo/pull/2103)
|
||||
* Add Retry-After header constant [#2078](https://github.com/labstack/echo/pull/2078)
|
||||
* Upgrade `go` directive in `go.mod` to 1.17 [#2049](https://github.com/labstack/echo/pull/2049)
|
||||
* Add Pagoda [#2077](https://github.com/labstack/echo/pull/2077) and Souin [#2069](https://github.com/labstack/echo/pull/2069) to 3rd-party middlewares in README
|
||||
|
||||
## v4.6.3 - 2022-01-10
|
||||
|
||||
**Fixes**
|
||||
|
||||
16
vendor/github.com/labstack/echo/v4/README.md
generated
vendored
16
vendor/github.com/labstack/echo/v4/README.md
generated
vendored
@@ -5,7 +5,6 @@
|
||||
[](https://goreportcard.com/report/github.com/labstack/echo)
|
||||
[](https://travis-ci.org/labstack/echo)
|
||||
[](https://codecov.io/gh/labstack/echo)
|
||||
[](https://gitter.im/labstack/echo)
|
||||
[](https://github.com/labstack/echo/discussions)
|
||||
[](https://twitter.com/labstack)
|
||||
[](https://raw.githubusercontent.com/labstack/echo/master/LICENSE)
|
||||
@@ -92,10 +91,23 @@ func hello(c echo.Context) error {
|
||||
}
|
||||
```
|
||||
|
||||
# Third-party middlewares
|
||||
|
||||
| Repository | Description |
|
||||
|------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| [github.com/labstack/echo-contrib](https://github.com/labstack/echo-contrib) | (by Echo team) [casbin](https://github.com/casbin/casbin), [gorilla/sessions](https://github.com/gorilla/sessions), [jaegertracing](github.com/uber/jaeger-client-go), [prometheus](https://github.com/prometheus/client_golang/), [pprof](https://pkg.go.dev/net/http/pprof), [zipkin](https://github.com/openzipkin/zipkin-go) middlewares |
|
||||
| [deepmap/oapi-codegen](https://github.com/deepmap/oapi-codegen) | Automatically generate RESTful API documentation with [OpenAPI](https://swagger.io/specification/) Client and Server Code Generator |
|
||||
| [github.com/swaggo/echo-swagger](https://github.com/swaggo/echo-swagger) | Automatically generate RESTful API documentation with [Swagger](https://swagger.io/) 2.0. |
|
||||
| [github.com/ziflex/lecho](https://github.com/ziflex/lecho) | [Zerolog](https://github.com/rs/zerolog) logging library wrapper for Echo logger interface. |
|
||||
| [github.com/brpaz/echozap](https://github.com/brpaz/echozap) | Uber´s [Zap](https://github.com/uber-go/zap) logging library wrapper for Echo logger interface. |
|
||||
| [github.com/darkweak/souin/plugins/echo](https://github.com/darkweak/souin/tree/master/plugins/echo) | HTTP cache system based on [Souin](https://github.com/darkweak/souin) to automatically get your endpoints cached. It supports some distributed and non-distributed storage systems depending your needs. |
|
||||
| [github.com/mikestefanello/pagoda](https://github.com/mikestefanello/pagoda) | Rapid, easy full-stack web development starter kit built with Echo.
|
||||
|
||||
Please send a PR to add your own library here.
|
||||
|
||||
## Help
|
||||
|
||||
- [Forum](https://github.com/labstack/echo/discussions)
|
||||
- [Chat](https://gitter.im/labstack/echo)
|
||||
|
||||
## Contribute
|
||||
|
||||
|
||||
10
vendor/github.com/labstack/echo/v4/bind.go
generated
vendored
10
vendor/github.com/labstack/echo/v4/bind.go
generated
vendored
@@ -111,11 +111,11 @@ func (b *DefaultBinder) Bind(i interface{}, c Context) (err error) {
|
||||
if err := b.BindPathParams(c, i); err != nil {
|
||||
return err
|
||||
}
|
||||
// Issue #1670 - Query params are binded only for GET/DELETE and NOT for usual request with body (POST/PUT/PATCH)
|
||||
// Reasoning here is that parameters in query and bind destination struct could have UNEXPECTED matches and results due that.
|
||||
// i.e. is `&id=1&lang=en` from URL same as `{"id":100,"lang":"de"}` request body and which one should have priority when binding.
|
||||
// This HTTP method check restores pre v4.1.11 behavior and avoids different problems when query is mixed with body
|
||||
if c.Request().Method == http.MethodGet || c.Request().Method == http.MethodDelete {
|
||||
// Only bind query parameters for GET/DELETE/HEAD to avoid unexpected behavior with destination struct binding from body.
|
||||
// For example a request URL `&id=1&lang=en` with body `{"id":100,"lang":"de"}` would lead to precedence issues.
|
||||
// The HTTP method check restores pre-v4.1.11 behavior to avoid these problems (see issue #1670)
|
||||
method := c.Request().Method
|
||||
if method == http.MethodGet || method == http.MethodDelete || method == http.MethodHead {
|
||||
if err = b.BindQueryParams(c, i); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
32
vendor/github.com/labstack/echo/v4/context.go
generated
vendored
32
vendor/github.com/labstack/echo/v4/context.go
generated
vendored
@@ -9,8 +9,6 @@ import (
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
@@ -210,6 +208,13 @@ type (
|
||||
}
|
||||
)
|
||||
|
||||
const (
|
||||
// ContextKeyHeaderAllow is set by Router for getting value for `Allow` header in later stages of handler call chain.
|
||||
// Allow header is mandatory for status 405 (method not found) and useful for OPTIONS method requests.
|
||||
// It is added to context only when Router does not find matching method handler for request.
|
||||
ContextKeyHeaderAllow = "echo_header_allow"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultMemory = 32 << 20 // 32 MB
|
||||
indexPage = "index.html"
|
||||
@@ -562,29 +567,6 @@ func (c *context) Stream(code int, contentType string, r io.Reader) (err error)
|
||||
return
|
||||
}
|
||||
|
||||
func (c *context) File(file string) (err error) {
|
||||
f, err := os.Open(file)
|
||||
if err != nil {
|
||||
return NotFoundHandler(c)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
fi, _ := f.Stat()
|
||||
if fi.IsDir() {
|
||||
file = filepath.Join(file, indexPage)
|
||||
f, err = os.Open(file)
|
||||
if err != nil {
|
||||
return NotFoundHandler(c)
|
||||
}
|
||||
defer f.Close()
|
||||
if fi, err = f.Stat(); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
http.ServeContent(c.Response(), c.Request(), fi.Name(), fi.ModTime(), f)
|
||||
return
|
||||
}
|
||||
|
||||
func (c *context) Attachment(file, name string) error {
|
||||
return c.contentDisposition(file, name, "attachment")
|
||||
}
|
||||
|
||||
33
vendor/github.com/labstack/echo/v4/context_fs.go
generated
vendored
Normal file
33
vendor/github.com/labstack/echo/v4/context_fs.go
generated
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
//go:build !go1.16
|
||||
// +build !go1.16
|
||||
|
||||
package echo
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
func (c *context) File(file string) (err error) {
|
||||
f, err := os.Open(file)
|
||||
if err != nil {
|
||||
return NotFoundHandler(c)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
fi, _ := f.Stat()
|
||||
if fi.IsDir() {
|
||||
file = filepath.Join(file, indexPage)
|
||||
f, err = os.Open(file)
|
||||
if err != nil {
|
||||
return NotFoundHandler(c)
|
||||
}
|
||||
defer f.Close()
|
||||
if fi, err = f.Stat(); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
http.ServeContent(c.Response(), c.Request(), fi.Name(), fi.ModTime(), f)
|
||||
return
|
||||
}
|
||||
52
vendor/github.com/labstack/echo/v4/context_fs_go1.16.go
generated
vendored
Normal file
52
vendor/github.com/labstack/echo/v4/context_fs_go1.16.go
generated
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
//go:build go1.16
|
||||
// +build go1.16
|
||||
|
||||
package echo
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
"io/fs"
|
||||
"net/http"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
func (c *context) File(file string) error {
|
||||
return fsFile(c, file, c.echo.Filesystem)
|
||||
}
|
||||
|
||||
// FileFS serves file from given file system.
|
||||
//
|
||||
// When dealing with `embed.FS` use `fs := echo.MustSubFS(fs, "rootDirectory") to create sub fs which uses necessary
|
||||
// prefix for directory path. This is necessary as `//go:embed assets/images` embeds files with paths
|
||||
// including `assets/images` as their prefix.
|
||||
func (c *context) FileFS(file string, filesystem fs.FS) error {
|
||||
return fsFile(c, file, filesystem)
|
||||
}
|
||||
|
||||
func fsFile(c Context, file string, filesystem fs.FS) error {
|
||||
f, err := filesystem.Open(file)
|
||||
if err != nil {
|
||||
return ErrNotFound
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
fi, _ := f.Stat()
|
||||
if fi.IsDir() {
|
||||
file = filepath.ToSlash(filepath.Join(file, indexPage)) // ToSlash is necessary for Windows. fs.Open and os.Open are different in that aspect.
|
||||
f, err = filesystem.Open(file)
|
||||
if err != nil {
|
||||
return ErrNotFound
|
||||
}
|
||||
defer f.Close()
|
||||
if fi, err = f.Stat(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
ff, ok := f.(io.ReadSeeker)
|
||||
if !ok {
|
||||
return errors.New("file does not implement io.ReadSeeker")
|
||||
}
|
||||
http.ServeContent(c.Response(), c.Request(), fi.Name(), fi.ModTime(), ff)
|
||||
return nil
|
||||
}
|
||||
85
vendor/github.com/labstack/echo/v4/echo.go
generated
vendored
85
vendor/github.com/labstack/echo/v4/echo.go
generated
vendored
@@ -47,9 +47,6 @@ import (
|
||||
stdLog "log"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"sync"
|
||||
@@ -66,6 +63,7 @@ import (
|
||||
type (
|
||||
// Echo is the top-level framework instance.
|
||||
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.
|
||||
@@ -77,7 +75,6 @@ type (
|
||||
maxParam *int
|
||||
router *Router
|
||||
routers map[string]*Router
|
||||
notFoundHandler HandlerFunc
|
||||
pool sync.Pool
|
||||
Server *http.Server
|
||||
TLSServer *http.Server
|
||||
@@ -113,10 +110,10 @@ type (
|
||||
}
|
||||
|
||||
// MiddlewareFunc defines a function to process middleware.
|
||||
MiddlewareFunc func(HandlerFunc) HandlerFunc
|
||||
MiddlewareFunc func(next HandlerFunc) HandlerFunc
|
||||
|
||||
// HandlerFunc defines a function to serve HTTP requests.
|
||||
HandlerFunc func(Context) error
|
||||
HandlerFunc func(c Context) error
|
||||
|
||||
// HTTPErrorHandler is a centralized HTTP error handler.
|
||||
HTTPErrorHandler func(error, Context)
|
||||
@@ -190,8 +187,12 @@ const (
|
||||
|
||||
// Headers
|
||||
const (
|
||||
HeaderAccept = "Accept"
|
||||
HeaderAcceptEncoding = "Accept-Encoding"
|
||||
HeaderAccept = "Accept"
|
||||
HeaderAcceptEncoding = "Accept-Encoding"
|
||||
// HeaderAllow is the name of the "Allow" header field used to list the set of methods
|
||||
// advertised as supported by the target resource. Returning an Allow header is mandatory
|
||||
// for status 405 (method not found) and useful for the OPTIONS method in responses.
|
||||
// See RFC 7231: https://datatracker.ietf.org/doc/html/rfc7231#section-7.4.1
|
||||
HeaderAllow = "Allow"
|
||||
HeaderAuthorization = "Authorization"
|
||||
HeaderContentDisposition = "Content-Disposition"
|
||||
@@ -203,6 +204,7 @@ const (
|
||||
HeaderIfModifiedSince = "If-Modified-Since"
|
||||
HeaderLastModified = "Last-Modified"
|
||||
HeaderLocation = "Location"
|
||||
HeaderRetryAfter = "Retry-After"
|
||||
HeaderUpgrade = "Upgrade"
|
||||
HeaderVary = "Vary"
|
||||
HeaderWWWAuthenticate = "WWW-Authenticate"
|
||||
@@ -212,12 +214,14 @@ const (
|
||||
HeaderXForwardedSsl = "X-Forwarded-Ssl"
|
||||
HeaderXUrlScheme = "X-Url-Scheme"
|
||||
HeaderXHTTPMethodOverride = "X-HTTP-Method-Override"
|
||||
HeaderXRealIP = "X-Real-IP"
|
||||
HeaderXRequestID = "X-Request-ID"
|
||||
HeaderXCorrelationID = "X-Correlation-ID"
|
||||
HeaderXRealIP = "X-Real-Ip"
|
||||
HeaderXRequestID = "X-Request-Id"
|
||||
HeaderXCorrelationID = "X-Correlation-Id"
|
||||
HeaderXRequestedWith = "X-Requested-With"
|
||||
HeaderServer = "Server"
|
||||
HeaderOrigin = "Origin"
|
||||
HeaderCacheControl = "Cache-Control"
|
||||
HeaderConnection = "Connection"
|
||||
|
||||
// Access control
|
||||
HeaderAccessControlRequestMethod = "Access-Control-Request-Method"
|
||||
@@ -242,7 +246,7 @@ const (
|
||||
|
||||
const (
|
||||
// Version of Echo
|
||||
Version = "4.6.3"
|
||||
Version = "4.7.0"
|
||||
website = "https://echo.labstack.com"
|
||||
// http://patorjk.com/software/taag/#p=display&f=Small%20Slant&t=Echo
|
||||
banner = `
|
||||
@@ -302,6 +306,12 @@ var (
|
||||
}
|
||||
|
||||
MethodNotAllowedHandler = func(c Context) error {
|
||||
// See RFC 7231 section 7.4.1: An origin server MUST generate an Allow field in a 405 (Method Not Allowed)
|
||||
// response and MAY do so in any other response. For disabled resources an empty Allow header may be returned
|
||||
routerAllowMethods, ok := c.Get(ContextKeyHeaderAllow).(string)
|
||||
if ok && routerAllowMethods != "" {
|
||||
c.Response().Header().Set(HeaderAllow, routerAllowMethods)
|
||||
}
|
||||
return ErrMethodNotAllowed
|
||||
}
|
||||
)
|
||||
@@ -309,8 +319,9 @@ var (
|
||||
// New creates an instance of Echo.
|
||||
func New() (e *Echo) {
|
||||
e = &Echo{
|
||||
Server: new(http.Server),
|
||||
TLSServer: new(http.Server),
|
||||
filesystem: createFilesystem(),
|
||||
Server: new(http.Server),
|
||||
TLSServer: new(http.Server),
|
||||
AutoTLSManager: autocert.Manager{
|
||||
Prompt: autocert.AcceptTOS,
|
||||
},
|
||||
@@ -489,50 +500,6 @@ func (e *Echo) Match(methods []string, path string, handler HandlerFunc, middlew
|
||||
return routes
|
||||
}
|
||||
|
||||
// Static registers a new route with path prefix to serve static files from the
|
||||
// provided root directory.
|
||||
func (e *Echo) Static(prefix, root string) *Route {
|
||||
if root == "" {
|
||||
root = "." // For security we want to restrict to CWD.
|
||||
}
|
||||
return e.static(prefix, root, e.GET)
|
||||
}
|
||||
|
||||
func (common) static(prefix, root string, get func(string, HandlerFunc, ...MiddlewareFunc) *Route) *Route {
|
||||
h := func(c Context) error {
|
||||
p, err := url.PathUnescape(c.Param("*"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
name := filepath.Join(root, filepath.Clean("/"+p)) // "/"+ for security
|
||||
fi, err := os.Stat(name)
|
||||
if err != nil {
|
||||
// The access path does not exist
|
||||
return NotFoundHandler(c)
|
||||
}
|
||||
|
||||
// If the request is for a directory and does not end with "/"
|
||||
p = c.Request().URL.Path // path must not be empty.
|
||||
if fi.IsDir() && p[len(p)-1] != '/' {
|
||||
// Redirect to ends with "/"
|
||||
return c.Redirect(http.StatusMovedPermanently, p+"/")
|
||||
}
|
||||
return c.File(name)
|
||||
}
|
||||
// Handle added routes based on trailing slash:
|
||||
// /prefix => exact route "/prefix" + any route "/prefix/*"
|
||||
// /prefix/ => only any route "/prefix/*"
|
||||
if prefix != "" {
|
||||
if prefix[len(prefix)-1] == '/' {
|
||||
// Only add any route for intentional trailing slash
|
||||
return get(prefix+"*", h)
|
||||
}
|
||||
get(prefix, h)
|
||||
}
|
||||
return get(prefix+"/*", h)
|
||||
}
|
||||
|
||||
func (common) file(path, file string, get func(string, HandlerFunc, ...MiddlewareFunc) *Route,
|
||||
m ...MiddlewareFunc) *Route {
|
||||
return get(path, func(c Context) error {
|
||||
@@ -643,7 +610,7 @@ func (e *Echo) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
// Acquire context
|
||||
c := e.pool.Get().(*context)
|
||||
c.Reset(r, w)
|
||||
h := NotFoundHandler
|
||||
var h func(Context) error
|
||||
|
||||
if e.premiddleware == nil {
|
||||
e.findRouter(r.Host).Find(r.Method, GetPath(r), c)
|
||||
|
||||
62
vendor/github.com/labstack/echo/v4/echo_fs.go
generated
vendored
Normal file
62
vendor/github.com/labstack/echo/v4/echo_fs.go
generated
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
//go:build !go1.16
|
||||
// +build !go1.16
|
||||
|
||||
package echo
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
type filesystem struct {
|
||||
}
|
||||
|
||||
func createFilesystem() filesystem {
|
||||
return filesystem{}
|
||||
}
|
||||
|
||||
// Static registers a new route with path prefix to serve static files from the
|
||||
// provided root directory.
|
||||
func (e *Echo) Static(prefix, root string) *Route {
|
||||
if root == "" {
|
||||
root = "." // For security we want to restrict to CWD.
|
||||
}
|
||||
return e.static(prefix, root, e.GET)
|
||||
}
|
||||
|
||||
func (common) static(prefix, root string, get func(string, HandlerFunc, ...MiddlewareFunc) *Route) *Route {
|
||||
h := func(c Context) error {
|
||||
p, err := url.PathUnescape(c.Param("*"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
name := filepath.Join(root, filepath.Clean("/"+p)) // "/"+ for security
|
||||
fi, err := os.Stat(name)
|
||||
if err != nil {
|
||||
// The access path does not exist
|
||||
return NotFoundHandler(c)
|
||||
}
|
||||
|
||||
// If the request is for a directory and does not end with "/"
|
||||
p = c.Request().URL.Path // path must not be empty.
|
||||
if fi.IsDir() && p[len(p)-1] != '/' {
|
||||
// Redirect to ends with "/"
|
||||
return c.Redirect(http.StatusMovedPermanently, p+"/")
|
||||
}
|
||||
return c.File(name)
|
||||
}
|
||||
// Handle added routes based on trailing slash:
|
||||
// /prefix => exact route "/prefix" + any route "/prefix/*"
|
||||
// /prefix/ => only any route "/prefix/*"
|
||||
if prefix != "" {
|
||||
if prefix[len(prefix)-1] == '/' {
|
||||
// Only add any route for intentional trailing slash
|
||||
return get(prefix+"*", h)
|
||||
}
|
||||
get(prefix, h)
|
||||
}
|
||||
return get(prefix+"/*", h)
|
||||
}
|
||||
145
vendor/github.com/labstack/echo/v4/echo_fs_go1.16.go
generated
vendored
Normal file
145
vendor/github.com/labstack/echo/v4/echo_fs_go1.16.go
generated
vendored
Normal file
@@ -0,0 +1,145 @@
|
||||
//go:build go1.16
|
||||
// +build go1.16
|
||||
|
||||
package echo
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type filesystem struct {
|
||||
// Filesystem is file system used by Static and File handlers to access files.
|
||||
// Defaults to os.DirFS(".")
|
||||
//
|
||||
// When dealing with `embed.FS` use `fs := echo.MustSubFS(fs, "rootDirectory") to create sub fs which uses necessary
|
||||
// prefix for directory path. This is necessary as `//go:embed assets/images` embeds files with paths
|
||||
// including `assets/images` as their prefix.
|
||||
Filesystem fs.FS
|
||||
}
|
||||
|
||||
func createFilesystem() filesystem {
|
||||
return filesystem{
|
||||
Filesystem: newDefaultFS(),
|
||||
}
|
||||
}
|
||||
|
||||
// Static registers a new route with path prefix to serve static files from the provided root directory.
|
||||
func (e *Echo) Static(pathPrefix, fsRoot string) *Route {
|
||||
subFs := MustSubFS(e.Filesystem, fsRoot)
|
||||
return e.Add(
|
||||
http.MethodGet,
|
||||
pathPrefix+"*",
|
||||
StaticDirectoryHandler(subFs, false),
|
||||
)
|
||||
}
|
||||
|
||||
// StaticFS registers a new route with path prefix to serve static files from the provided file system.
|
||||
//
|
||||
// When dealing with `embed.FS` use `fs := echo.MustSubFS(fs, "rootDirectory") to create sub fs which uses necessary
|
||||
// prefix for directory path. This is necessary as `//go:embed assets/images` embeds files with paths
|
||||
// including `assets/images` as their prefix.
|
||||
func (e *Echo) StaticFS(pathPrefix string, filesystem fs.FS) *Route {
|
||||
return e.Add(
|
||||
http.MethodGet,
|
||||
pathPrefix+"*",
|
||||
StaticDirectoryHandler(filesystem, false),
|
||||
)
|
||||
}
|
||||
|
||||
// StaticDirectoryHandler creates handler function to serve files from provided file system
|
||||
// When disablePathUnescaping is set then file name from path is not unescaped and is served as is.
|
||||
func StaticDirectoryHandler(fileSystem fs.FS, disablePathUnescaping bool) HandlerFunc {
|
||||
return func(c Context) error {
|
||||
p := c.Param("*")
|
||||
if !disablePathUnescaping { // when router is already unescaping we do not want to do is twice
|
||||
tmpPath, err := url.PathUnescape(p)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to unescape path variable: %w", err)
|
||||
}
|
||||
p = tmpPath
|
||||
}
|
||||
|
||||
// fs.FS.Open() already assumes that file names are relative to FS root path and considers name with prefix `/` as invalid
|
||||
name := filepath.ToSlash(filepath.Clean(strings.TrimPrefix(p, "/")))
|
||||
fi, err := fs.Stat(fileSystem, name)
|
||||
if err != nil {
|
||||
return ErrNotFound
|
||||
}
|
||||
|
||||
// If the request is for a directory and does not end with "/"
|
||||
p = c.Request().URL.Path // path must not be empty.
|
||||
if fi.IsDir() && len(p) > 0 && p[len(p)-1] != '/' {
|
||||
// Redirect to ends with "/"
|
||||
return c.Redirect(http.StatusMovedPermanently, p+"/")
|
||||
}
|
||||
return fsFile(c, name, fileSystem)
|
||||
}
|
||||
}
|
||||
|
||||
// FileFS registers a new route with path to serve file from the provided file system.
|
||||
func (e *Echo) FileFS(path, file string, filesystem fs.FS, m ...MiddlewareFunc) *Route {
|
||||
return e.GET(path, StaticFileHandler(file, filesystem), m...)
|
||||
}
|
||||
|
||||
// StaticFileHandler creates handler function to serve file from provided file system
|
||||
func StaticFileHandler(file string, filesystem fs.FS) HandlerFunc {
|
||||
return func(c Context) error {
|
||||
return fsFile(c, file, filesystem)
|
||||
}
|
||||
}
|
||||
|
||||
// defaultFS emulates os.Open behaviour with filesystem opened by `os.DirFs`. Difference between `os.Open` and `fs.Open`
|
||||
// is that FS does not allow to open path that start with `..` or `/` etc. For example previously you could have `../images`
|
||||
// in your application but `fs := os.DirFS("./")` would not allow you to use `fs.Open("../images")` and this would break
|
||||
// all old applications that rely on being able to traverse up from current executable run path.
|
||||
// NB: private because you really should use fs.FS implementation instances
|
||||
type defaultFS struct {
|
||||
prefix string
|
||||
fs fs.FS
|
||||
}
|
||||
|
||||
func newDefaultFS() *defaultFS {
|
||||
dir, _ := os.Getwd()
|
||||
return &defaultFS{
|
||||
prefix: dir,
|
||||
fs: os.DirFS(dir),
|
||||
}
|
||||
}
|
||||
|
||||
func (fs defaultFS) Open(name string) (fs.File, error) {
|
||||
return fs.fs.Open(name)
|
||||
}
|
||||
|
||||
func subFS(currentFs fs.FS, root string) (fs.FS, error) {
|
||||
root = filepath.ToSlash(filepath.Clean(root)) // note: fs.FS operates only with slashes. `ToSlash` is necessary for Windows
|
||||
if dFS, ok := currentFs.(*defaultFS); ok {
|
||||
// we need to make exception for `defaultFS` instances as it interprets root prefix differently from fs.FS to
|
||||
// allow cases when root is given as `../somepath` which is not valid for fs.FS
|
||||
root = filepath.Join(dFS.prefix, root)
|
||||
return &defaultFS{
|
||||
prefix: root,
|
||||
fs: os.DirFS(root),
|
||||
}, nil
|
||||
}
|
||||
return fs.Sub(currentFs, root)
|
||||
}
|
||||
|
||||
// MustSubFS creates sub FS from current filesystem or panic on failure.
|
||||
// Panic happens when `fsRoot` contains invalid path according to `fs.ValidPath` rules.
|
||||
//
|
||||
// MustSubFS is helpful when dealing with `embed.FS` because for example `//go:embed assets/images` embeds files with
|
||||
// paths including `assets/images` as their prefix. In that case use `fs := echo.MustSubFS(fs, "rootDirectory") to
|
||||
// create sub fs which uses necessary prefix for directory path.
|
||||
func MustSubFS(currentFs fs.FS, fsRoot string) fs.FS {
|
||||
subFs, err := subFS(currentFs, fsRoot)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("can not create sub FS, invalid root given, err: %w", err))
|
||||
}
|
||||
return subFs
|
||||
}
|
||||
5
vendor/github.com/labstack/echo/v4/group.go
generated
vendored
5
vendor/github.com/labstack/echo/v4/group.go
generated
vendored
@@ -102,11 +102,6 @@ func (g *Group) Group(prefix string, middleware ...MiddlewareFunc) (sg *Group) {
|
||||
return
|
||||
}
|
||||
|
||||
// Static implements `Echo#Static()` for sub-routes within the Group.
|
||||
func (g *Group) Static(prefix, root string) {
|
||||
g.static(prefix, root, g.GET)
|
||||
}
|
||||
|
||||
// File implements `Echo#File()` for sub-routes within the Group.
|
||||
func (g *Group) File(path, file string) {
|
||||
g.file(path, file, g.GET)
|
||||
|
||||
9
vendor/github.com/labstack/echo/v4/group_fs.go
generated
vendored
Normal file
9
vendor/github.com/labstack/echo/v4/group_fs.go
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
//go:build !go1.16
|
||||
// +build !go1.16
|
||||
|
||||
package echo
|
||||
|
||||
// Static implements `Echo#Static()` for sub-routes within the Group.
|
||||
func (g *Group) Static(prefix, root string) {
|
||||
g.static(prefix, root, g.GET)
|
||||
}
|
||||
33
vendor/github.com/labstack/echo/v4/group_fs_go1.16.go
generated
vendored
Normal file
33
vendor/github.com/labstack/echo/v4/group_fs_go1.16.go
generated
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
//go:build go1.16
|
||||
// +build go1.16
|
||||
|
||||
package echo
|
||||
|
||||
import (
|
||||
"io/fs"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// Static implements `Echo#Static()` for sub-routes within the Group.
|
||||
func (g *Group) Static(pathPrefix, fsRoot string) {
|
||||
subFs := MustSubFS(g.echo.Filesystem, fsRoot)
|
||||
g.StaticFS(pathPrefix, subFs)
|
||||
}
|
||||
|
||||
// StaticFS implements `Echo#StaticFS()` for sub-routes within the Group.
|
||||
//
|
||||
// When dealing with `embed.FS` use `fs := echo.MustSubFS(fs, "rootDirectory") to create sub fs which uses necessary
|
||||
// prefix for directory path. This is necessary as `//go:embed assets/images` embeds files with paths
|
||||
// including `assets/images` as their prefix.
|
||||
func (g *Group) StaticFS(pathPrefix string, filesystem fs.FS) {
|
||||
g.Add(
|
||||
http.MethodGet,
|
||||
pathPrefix+"*",
|
||||
StaticDirectoryHandler(filesystem, false),
|
||||
)
|
||||
}
|
||||
|
||||
// FileFS implements `Echo#FileFS()` for sub-routes within the Group.
|
||||
func (g *Group) FileFS(path, file string, filesystem fs.FS, m ...MiddlewareFunc) *Route {
|
||||
return g.GET(path, StaticFileHandler(file, filesystem), m...)
|
||||
}
|
||||
142
vendor/github.com/labstack/echo/v4/ip.go
generated
vendored
142
vendor/github.com/labstack/echo/v4/ip.go
generated
vendored
@@ -6,6 +6,130 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
/**
|
||||
By: https://github.com/tmshn (See: https://github.com/labstack/echo/pull/1478 , https://github.com/labstack/echox/pull/134 )
|
||||
Source: https://echo.labstack.com/guide/ip-address/
|
||||
|
||||
IP address plays fundamental role in HTTP; it's used for access control, auditing, geo-based access analysis and more.
|
||||
Echo provides handy method [`Context#RealIP()`](https://godoc.org/github.com/labstack/echo#Context) for that.
|
||||
|
||||
However, it is not trivial to retrieve the _real_ IP address from requests especially when you put L7 proxies before the application.
|
||||
In such situation, _real_ IP needs to be relayed on HTTP layer from proxies to your app, but you must not trust HTTP headers unconditionally.
|
||||
Otherwise, you might give someone a chance of deceiving you. **A security risk!**
|
||||
|
||||
To retrieve IP address reliably/securely, you must let your application be aware of the entire architecture of your infrastructure.
|
||||
In Echo, this can be done by configuring `Echo#IPExtractor` appropriately.
|
||||
This guides show you why and how.
|
||||
|
||||
> Note: if you dont' set `Echo#IPExtractor` explicitly, Echo fallback to legacy behavior, which is not a good choice.
|
||||
|
||||
Let's start from two questions to know the right direction:
|
||||
|
||||
1. Do you put any HTTP (L7) proxy in front of the application?
|
||||
- It includes both cloud solutions (such as AWS ALB or GCP HTTP LB) and OSS ones (such as Nginx, Envoy or Istio ingress gateway).
|
||||
2. If yes, what HTTP header do your proxies use to pass client IP to the application?
|
||||
|
||||
## Case 1. With no proxy
|
||||
|
||||
If you put no proxy (e.g.: directory facing to the internet), all you need to (and have to) see is IP address from network layer.
|
||||
Any HTTP header is untrustable because the clients have full control what headers to be set.
|
||||
|
||||
In this case, use `echo.ExtractIPDirect()`.
|
||||
|
||||
```go
|
||||
e.IPExtractor = echo.ExtractIPDirect()
|
||||
```
|
||||
|
||||
## Case 2. With proxies using `X-Forwarded-For` header
|
||||
|
||||
[`X-Forwared-For` (XFF)](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For) is the popular header
|
||||
to relay clients' IP addresses.
|
||||
At each hop on the proxies, they append the request IP address at the end of the header.
|
||||
|
||||
Following example diagram illustrates this behavior.
|
||||
|
||||
```text
|
||||
┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
|
||||
│ "Origin" │───────────>│ Proxy 1 │───────────>│ Proxy 2 │───────────>│ Your app │
|
||||
│ (IP: a) │ │ (IP: b) │ │ (IP: c) │ │ │
|
||||
└──────────┘ └──────────┘ └──────────┘ └──────────┘
|
||||
|
||||
Case 1.
|
||||
XFF: "" "a" "a, b"
|
||||
~~~~~~
|
||||
Case 2.
|
||||
XFF: "x" "x, a" "x, a, b"
|
||||
~~~~~~~~~
|
||||
↑ What your app will see
|
||||
```
|
||||
|
||||
In this case, use **first _untrustable_ IP reading from right**. Never use first one reading from left, as it is
|
||||
configurable by client. Here "trustable" means "you are sure the IP address belongs to your infrastructre".
|
||||
In above example, if `b` and `c` are trustable, the IP address of the client is `a` for both cases, never be `x`.
|
||||
|
||||
In Echo, use `ExtractIPFromXFFHeader(...TrustOption)`.
|
||||
|
||||
```go
|
||||
e.IPExtractor = echo.ExtractIPFromXFFHeader()
|
||||
```
|
||||
|
||||
By default, it trusts internal IP addresses (loopback, link-local unicast, private-use and unique local address
|
||||
from [RFC6890](https://tools.ietf.org/html/rfc6890), [RFC4291](https://tools.ietf.org/html/rfc4291) and
|
||||
[RFC4193](https://tools.ietf.org/html/rfc4193)).
|
||||
To control this behavior, use [`TrustOption`](https://godoc.org/github.com/labstack/echo#TrustOption)s.
|
||||
|
||||
E.g.:
|
||||
|
||||
```go
|
||||
e.IPExtractor = echo.ExtractIPFromXFFHeader(
|
||||
TrustLinkLocal(false),
|
||||
TrustIPRanges(lbIPRange),
|
||||
)
|
||||
```
|
||||
|
||||
- Ref: https://godoc.org/github.com/labstack/echo#TrustOption
|
||||
|
||||
## Case 3. With proxies using `X-Real-IP` header
|
||||
|
||||
`X-Real-IP` is another HTTP header to relay clients' IP addresses, but it carries only one address unlike XFF.
|
||||
|
||||
If your proxies set this header, use `ExtractIPFromRealIPHeader(...TrustOption)`.
|
||||
|
||||
```go
|
||||
e.IPExtractor = echo.ExtractIPFromRealIPHeader()
|
||||
```
|
||||
|
||||
Again, it trusts internal IP addresses by default (loopback, link-local unicast, private-use and unique local address
|
||||
from [RFC6890](https://tools.ietf.org/html/rfc6890), [RFC4291](https://tools.ietf.org/html/rfc4291) and
|
||||
[RFC4193](https://tools.ietf.org/html/rfc4193)).
|
||||
To control this behavior, use [`TrustOption`](https://godoc.org/github.com/labstack/echo#TrustOption)s.
|
||||
|
||||
- Ref: https://godoc.org/github.com/labstack/echo#TrustOption
|
||||
|
||||
> **Never forget** to configure the outermost proxy (i.e.; at the edge of your infrastructure) **not to pass through incoming headers**.
|
||||
> Otherwise there is a chance of fraud, as it is what clients can control.
|
||||
|
||||
## About default behavior
|
||||
|
||||
In default behavior, Echo sees all of first XFF header, X-Real-IP header and IP from network layer.
|
||||
|
||||
As you might already notice, after reading this article, this is not good.
|
||||
Sole reason this is default is just backward compatibility.
|
||||
|
||||
## Private IP ranges
|
||||
|
||||
See: https://en.wikipedia.org/wiki/Private_network
|
||||
|
||||
Private IPv4 address ranges (RFC 1918):
|
||||
* 10.0.0.0 – 10.255.255.255 (24-bit block)
|
||||
* 172.16.0.0 – 172.31.255.255 (20-bit block)
|
||||
* 192.168.0.0 – 192.168.255.255 (16-bit block)
|
||||
|
||||
Private IPv6 address ranges:
|
||||
* fc00::/7 address block = RFC 4193 Unique Local Addresses (ULA)
|
||||
|
||||
*/
|
||||
|
||||
type ipChecker struct {
|
||||
trustLoopback bool
|
||||
trustLinkLocal bool
|
||||
@@ -52,6 +176,7 @@ func newIPChecker(configs []TrustOption) *ipChecker {
|
||||
return checker
|
||||
}
|
||||
|
||||
// Go1.16+ added `ip.IsPrivate()` but until that use this implementation
|
||||
func isPrivateIPRange(ip net.IP) bool {
|
||||
if ip4 := ip.To4(); ip4 != nil {
|
||||
return ip4[0] == 10 ||
|
||||
@@ -87,10 +212,12 @@ type IPExtractor func(*http.Request) string
|
||||
// ExtractIPDirect extracts IP address using actual IP address.
|
||||
// Use this if your server faces to internet directory (i.e.: uses no proxy).
|
||||
func ExtractIPDirect() IPExtractor {
|
||||
return func(req *http.Request) string {
|
||||
ra, _, _ := net.SplitHostPort(req.RemoteAddr)
|
||||
return ra
|
||||
}
|
||||
return extractIP
|
||||
}
|
||||
|
||||
func extractIP(req *http.Request) string {
|
||||
ra, _, _ := net.SplitHostPort(req.RemoteAddr)
|
||||
return ra
|
||||
}
|
||||
|
||||
// ExtractIPFromRealIPHeader extracts IP address using x-real-ip header.
|
||||
@@ -98,14 +225,13 @@ func ExtractIPDirect() IPExtractor {
|
||||
func ExtractIPFromRealIPHeader(options ...TrustOption) IPExtractor {
|
||||
checker := newIPChecker(options)
|
||||
return func(req *http.Request) string {
|
||||
directIP := ExtractIPDirect()(req)
|
||||
realIP := req.Header.Get(HeaderXRealIP)
|
||||
if realIP != "" {
|
||||
if ip := net.ParseIP(directIP); ip != nil && checker.trust(ip) {
|
||||
if ip := net.ParseIP(realIP); ip != nil && checker.trust(ip) {
|
||||
return realIP
|
||||
}
|
||||
}
|
||||
return directIP
|
||||
return extractIP(req)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,7 +241,7 @@ func ExtractIPFromRealIPHeader(options ...TrustOption) IPExtractor {
|
||||
func ExtractIPFromXFFHeader(options ...TrustOption) IPExtractor {
|
||||
checker := newIPChecker(options)
|
||||
return func(req *http.Request) string {
|
||||
directIP := ExtractIPDirect()(req)
|
||||
directIP := extractIP(req)
|
||||
xffs := req.Header[HeaderXForwardedFor]
|
||||
if len(xffs) == 0 {
|
||||
return directIP
|
||||
|
||||
69
vendor/github.com/labstack/echo/v4/middleware/cors.go
generated
vendored
69
vendor/github.com/labstack/echo/v4/middleware/cors.go
generated
vendored
@@ -29,6 +29,8 @@ type (
|
||||
// AllowMethods defines a list methods allowed when accessing the resource.
|
||||
// This is used in response to a preflight request.
|
||||
// Optional. Default value DefaultCORSConfig.AllowMethods.
|
||||
// If `allowMethods` is left empty will fill for preflight request `Access-Control-Allow-Methods` header value
|
||||
// from `Allow` header that echo.Router set into context.
|
||||
AllowMethods []string `yaml:"allow_methods"`
|
||||
|
||||
// AllowHeaders defines a list of request headers that can be used when
|
||||
@@ -41,6 +43,8 @@ type (
|
||||
// a response to a preflight request, this indicates whether or not the
|
||||
// actual request can be made using credentials.
|
||||
// Optional. Default value false.
|
||||
// Security: avoid using `AllowCredentials = true` with `AllowOrigins = *`.
|
||||
// See http://blog.portswigger.net/2016/10/exploiting-cors-misconfigurations-for.html
|
||||
AllowCredentials bool `yaml:"allow_credentials"`
|
||||
|
||||
// ExposeHeaders defines a whitelist headers that clients are allowed to
|
||||
@@ -80,7 +84,9 @@ func CORSWithConfig(config CORSConfig) echo.MiddlewareFunc {
|
||||
if len(config.AllowOrigins) == 0 {
|
||||
config.AllowOrigins = DefaultCORSConfig.AllowOrigins
|
||||
}
|
||||
hasCustomAllowMethods := true
|
||||
if len(config.AllowMethods) == 0 {
|
||||
hasCustomAllowMethods = false
|
||||
config.AllowMethods = DefaultCORSConfig.AllowMethods
|
||||
}
|
||||
|
||||
@@ -109,10 +115,28 @@ func CORSWithConfig(config CORSConfig) echo.MiddlewareFunc {
|
||||
origin := req.Header.Get(echo.HeaderOrigin)
|
||||
allowOrigin := ""
|
||||
|
||||
preflight := req.Method == http.MethodOptions
|
||||
res.Header().Add(echo.HeaderVary, echo.HeaderOrigin)
|
||||
|
||||
// No Origin provided
|
||||
// Preflight request is an OPTIONS request, using three HTTP request headers: Access-Control-Request-Method,
|
||||
// Access-Control-Request-Headers, and the Origin header. See: https://developer.mozilla.org/en-US/docs/Glossary/Preflight_request
|
||||
// For simplicity we just consider method type and later `Origin` header.
|
||||
preflight := req.Method == http.MethodOptions
|
||||
|
||||
// Although router adds special handler in case of OPTIONS method we avoid calling next for OPTIONS in this middleware
|
||||
// as CORS requests do not have cookies / authentication headers by default, so we could get stuck in auth
|
||||
// middlewares by calling next(c).
|
||||
// But we still want to send `Allow` header as response in case of Non-CORS OPTIONS request as router default
|
||||
// handler does.
|
||||
routerAllowMethods := ""
|
||||
if preflight {
|
||||
tmpAllowMethods, ok := c.Get(echo.ContextKeyHeaderAllow).(string)
|
||||
if ok && tmpAllowMethods != "" {
|
||||
routerAllowMethods = tmpAllowMethods
|
||||
c.Response().Header().Set(echo.HeaderAllow, routerAllowMethods)
|
||||
}
|
||||
}
|
||||
|
||||
// No Origin provided. This is (probably) not request from actual browser - proceed executing middleware chain
|
||||
if origin == "" {
|
||||
if !preflight {
|
||||
return next(c)
|
||||
@@ -145,19 +169,15 @@ func CORSWithConfig(config CORSConfig) echo.MiddlewareFunc {
|
||||
}
|
||||
}
|
||||
|
||||
// Check allowed origin patterns
|
||||
for _, re := range allowOriginPatterns {
|
||||
if allowOrigin == "" {
|
||||
didx := strings.Index(origin, "://")
|
||||
if didx == -1 {
|
||||
continue
|
||||
}
|
||||
domAuth := origin[didx+3:]
|
||||
// to avoid regex cost by invalid long domain
|
||||
if len(domAuth) > 253 {
|
||||
break
|
||||
}
|
||||
|
||||
checkPatterns := false
|
||||
if allowOrigin == "" {
|
||||
// to avoid regex cost by invalid (long) domains (253 is domain name max limit)
|
||||
if len(origin) <= (253+3+5) && strings.Contains(origin, "://") {
|
||||
checkPatterns = true
|
||||
}
|
||||
}
|
||||
if checkPatterns {
|
||||
for _, re := range allowOriginPatterns {
|
||||
if match, _ := regexp.MatchString(re, origin); match {
|
||||
allowOrigin = origin
|
||||
break
|
||||
@@ -174,12 +194,13 @@ func CORSWithConfig(config CORSConfig) echo.MiddlewareFunc {
|
||||
return c.NoContent(http.StatusNoContent)
|
||||
}
|
||||
|
||||
res.Header().Set(echo.HeaderAccessControlAllowOrigin, allowOrigin)
|
||||
if config.AllowCredentials {
|
||||
res.Header().Set(echo.HeaderAccessControlAllowCredentials, "true")
|
||||
}
|
||||
|
||||
// Simple request
|
||||
if !preflight {
|
||||
res.Header().Set(echo.HeaderAccessControlAllowOrigin, allowOrigin)
|
||||
if config.AllowCredentials {
|
||||
res.Header().Set(echo.HeaderAccessControlAllowCredentials, "true")
|
||||
}
|
||||
if exposeHeaders != "" {
|
||||
res.Header().Set(echo.HeaderAccessControlExposeHeaders, exposeHeaders)
|
||||
}
|
||||
@@ -189,11 +210,13 @@ func CORSWithConfig(config CORSConfig) echo.MiddlewareFunc {
|
||||
// Preflight request
|
||||
res.Header().Add(echo.HeaderVary, echo.HeaderAccessControlRequestMethod)
|
||||
res.Header().Add(echo.HeaderVary, echo.HeaderAccessControlRequestHeaders)
|
||||
res.Header().Set(echo.HeaderAccessControlAllowOrigin, allowOrigin)
|
||||
res.Header().Set(echo.HeaderAccessControlAllowMethods, allowMethods)
|
||||
if config.AllowCredentials {
|
||||
res.Header().Set(echo.HeaderAccessControlAllowCredentials, "true")
|
||||
|
||||
if !hasCustomAllowMethods && routerAllowMethods != "" {
|
||||
res.Header().Set(echo.HeaderAccessControlAllowMethods, routerAllowMethods)
|
||||
} else {
|
||||
res.Header().Set(echo.HeaderAccessControlAllowMethods, allowMethods)
|
||||
}
|
||||
|
||||
if allowHeaders != "" {
|
||||
res.Header().Set(echo.HeaderAccessControlAllowHeaders, allowHeaders)
|
||||
} else {
|
||||
|
||||
110
vendor/github.com/labstack/echo/v4/middleware/csrf.go
generated
vendored
110
vendor/github.com/labstack/echo/v4/middleware/csrf.go
generated
vendored
@@ -2,9 +2,7 @@ package middleware
|
||||
|
||||
import (
|
||||
"crypto/subtle"
|
||||
"errors"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
@@ -21,13 +19,15 @@ type (
|
||||
TokenLength uint8 `yaml:"token_length"`
|
||||
// Optional. Default value 32.
|
||||
|
||||
// TokenLookup is a string in the form of "<source>:<key>" that is used
|
||||
// TokenLookup is a string in the form of "<source>:<name>" or "<source>:<name>,<source>:<name>" that is used
|
||||
// to extract token from the request.
|
||||
// Optional. Default value "header:X-CSRF-Token".
|
||||
// Possible values:
|
||||
// - "header:<name>"
|
||||
// - "form:<name>"
|
||||
// - "header:<name>" or "header:<name>:<cut-prefix>"
|
||||
// - "query:<name>"
|
||||
// - "form:<name>"
|
||||
// Multiple sources example:
|
||||
// - "header:X-CSRF-Token,query:csrf"
|
||||
TokenLookup string `yaml:"token_lookup"`
|
||||
|
||||
// Context key to store generated CSRF token into context.
|
||||
@@ -62,12 +62,11 @@ type (
|
||||
// Optional. Default value SameSiteDefaultMode.
|
||||
CookieSameSite http.SameSite `yaml:"cookie_same_site"`
|
||||
}
|
||||
|
||||
// csrfTokenExtractor defines a function that takes `echo.Context` and returns
|
||||
// either a token or an error.
|
||||
csrfTokenExtractor func(echo.Context) (string, error)
|
||||
)
|
||||
|
||||
// ErrCSRFInvalid is returned when CSRF check fails
|
||||
var ErrCSRFInvalid = echo.NewHTTPError(http.StatusForbidden, "invalid csrf token")
|
||||
|
||||
var (
|
||||
// DefaultCSRFConfig is the default CSRF middleware config.
|
||||
DefaultCSRFConfig = CSRFConfig{
|
||||
@@ -114,14 +113,9 @@ func CSRFWithConfig(config CSRFConfig) echo.MiddlewareFunc {
|
||||
config.CookieSecure = true
|
||||
}
|
||||
|
||||
// Initialize
|
||||
parts := strings.Split(config.TokenLookup, ":")
|
||||
extractor := csrfTokenFromHeader(parts[1])
|
||||
switch parts[0] {
|
||||
case "form":
|
||||
extractor = csrfTokenFromForm(parts[1])
|
||||
case "query":
|
||||
extractor = csrfTokenFromQuery(parts[1])
|
||||
extractors, err := createExtractors(config.TokenLookup, "")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return func(next echo.HandlerFunc) echo.HandlerFunc {
|
||||
@@ -130,28 +124,50 @@ func CSRFWithConfig(config CSRFConfig) echo.MiddlewareFunc {
|
||||
return next(c)
|
||||
}
|
||||
|
||||
req := c.Request()
|
||||
k, err := c.Cookie(config.CookieName)
|
||||
token := ""
|
||||
|
||||
// Generate token
|
||||
if err != nil {
|
||||
token = random.String(config.TokenLength)
|
||||
if k, err := c.Cookie(config.CookieName); err != nil {
|
||||
token = random.String(config.TokenLength) // Generate token
|
||||
} else {
|
||||
// Reuse token
|
||||
token = k.Value
|
||||
token = k.Value // Reuse token
|
||||
}
|
||||
|
||||
switch req.Method {
|
||||
switch c.Request().Method {
|
||||
case http.MethodGet, http.MethodHead, http.MethodOptions, http.MethodTrace:
|
||||
default:
|
||||
// Validate token only for requests which are not defined as 'safe' by RFC7231
|
||||
clientToken, err := extractor(c)
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, err.Error())
|
||||
var lastExtractorErr error
|
||||
var lastTokenErr error
|
||||
outer:
|
||||
for _, extractor := range extractors {
|
||||
clientTokens, err := extractor(c)
|
||||
if err != nil {
|
||||
lastExtractorErr = err
|
||||
continue
|
||||
}
|
||||
|
||||
for _, clientToken := range clientTokens {
|
||||
if validateCSRFToken(token, clientToken) {
|
||||
lastTokenErr = nil
|
||||
lastExtractorErr = nil
|
||||
break outer
|
||||
}
|
||||
lastTokenErr = ErrCSRFInvalid
|
||||
}
|
||||
}
|
||||
if !validateCSRFToken(token, clientToken) {
|
||||
return echo.NewHTTPError(http.StatusForbidden, "invalid csrf token")
|
||||
if lastTokenErr != nil {
|
||||
return lastTokenErr
|
||||
} else if lastExtractorErr != nil {
|
||||
// ugly part to preserve backwards compatible errors. someone could rely on them
|
||||
if lastExtractorErr == errQueryExtractorValueMissing {
|
||||
lastExtractorErr = echo.NewHTTPError(http.StatusBadRequest, "missing csrf token in the query string")
|
||||
} else if lastExtractorErr == errFormExtractorValueMissing {
|
||||
lastExtractorErr = echo.NewHTTPError(http.StatusBadRequest, "missing csrf token in the form parameter")
|
||||
} else if lastExtractorErr == errHeaderExtractorValueMissing {
|
||||
lastExtractorErr = echo.NewHTTPError(http.StatusBadRequest, "missing csrf token in request header")
|
||||
} else {
|
||||
lastExtractorErr = echo.NewHTTPError(http.StatusBadRequest, lastExtractorErr.Error())
|
||||
}
|
||||
return lastExtractorErr
|
||||
}
|
||||
}
|
||||
|
||||
@@ -184,38 +200,6 @@ func CSRFWithConfig(config CSRFConfig) echo.MiddlewareFunc {
|
||||
}
|
||||
}
|
||||
|
||||
// csrfTokenFromForm returns a `csrfTokenExtractor` that extracts token from the
|
||||
// provided request header.
|
||||
func csrfTokenFromHeader(header string) csrfTokenExtractor {
|
||||
return func(c echo.Context) (string, error) {
|
||||
return c.Request().Header.Get(header), nil
|
||||
}
|
||||
}
|
||||
|
||||
// csrfTokenFromForm returns a `csrfTokenExtractor` that extracts token from the
|
||||
// provided form parameter.
|
||||
func csrfTokenFromForm(param string) csrfTokenExtractor {
|
||||
return func(c echo.Context) (string, error) {
|
||||
token := c.FormValue(param)
|
||||
if token == "" {
|
||||
return "", errors.New("missing csrf token in the form parameter")
|
||||
}
|
||||
return token, nil
|
||||
}
|
||||
}
|
||||
|
||||
// csrfTokenFromQuery returns a `csrfTokenExtractor` that extracts token from the
|
||||
// provided query parameter.
|
||||
func csrfTokenFromQuery(param string) csrfTokenExtractor {
|
||||
return func(c echo.Context) (string, error) {
|
||||
token := c.QueryParam(param)
|
||||
if token == "" {
|
||||
return "", errors.New("missing csrf token in the query string")
|
||||
}
|
||||
return token, nil
|
||||
}
|
||||
}
|
||||
|
||||
func validateCSRFToken(token, clientToken string) bool {
|
||||
return subtle.ConstantTimeCompare([]byte(token), []byte(clientToken)) == 1
|
||||
}
|
||||
|
||||
184
vendor/github.com/labstack/echo/v4/middleware/extractor.go
generated
vendored
Normal file
184
vendor/github.com/labstack/echo/v4/middleware/extractor.go
generated
vendored
Normal file
@@ -0,0 +1,184 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/labstack/echo/v4"
|
||||
"net/textproto"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
// extractorLimit is arbitrary number to limit values extractor can return. this limits possible resource exhaustion
|
||||
// attack vector
|
||||
extractorLimit = 20
|
||||
)
|
||||
|
||||
var errHeaderExtractorValueMissing = errors.New("missing value in request header")
|
||||
var errHeaderExtractorValueInvalid = errors.New("invalid value in request header")
|
||||
var errQueryExtractorValueMissing = errors.New("missing value in the query string")
|
||||
var errParamExtractorValueMissing = errors.New("missing value in path params")
|
||||
var errCookieExtractorValueMissing = errors.New("missing value in cookies")
|
||||
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)
|
||||
|
||||
func createExtractors(lookups string, authScheme string) ([]ValuesExtractor, error) {
|
||||
if lookups == "" {
|
||||
return nil, nil
|
||||
}
|
||||
sources := strings.Split(lookups, ",")
|
||||
var extractors = make([]ValuesExtractor, 0)
|
||||
for _, source := range sources {
|
||||
parts := strings.Split(source, ":")
|
||||
if len(parts) < 2 {
|
||||
return nil, fmt.Errorf("extractor source for lookup could not be split into needed parts: %v", source)
|
||||
}
|
||||
|
||||
switch parts[0] {
|
||||
case "query":
|
||||
extractors = append(extractors, valuesFromQuery(parts[1]))
|
||||
case "param":
|
||||
extractors = append(extractors, valuesFromParam(parts[1]))
|
||||
case "cookie":
|
||||
extractors = append(extractors, valuesFromCookie(parts[1]))
|
||||
case "form":
|
||||
extractors = append(extractors, valuesFromForm(parts[1]))
|
||||
case "header":
|
||||
prefix := ""
|
||||
if len(parts) > 2 {
|
||||
prefix = parts[2]
|
||||
} else if authScheme != "" && parts[1] == echo.HeaderAuthorization {
|
||||
// backwards compatibility for JWT and KeyAuth:
|
||||
// * we only apply this fix to Authorization as header we use and uses prefixes like "Bearer <token-value>" etc
|
||||
// * previously header extractor assumed that auth-scheme/prefix had a space as suffix we need to retain that
|
||||
// behaviour for default values and Authorization header.
|
||||
prefix = authScheme
|
||||
if !strings.HasSuffix(prefix, " ") {
|
||||
prefix += " "
|
||||
}
|
||||
}
|
||||
extractors = append(extractors, valuesFromHeader(parts[1], prefix))
|
||||
}
|
||||
}
|
||||
return extractors, nil
|
||||
}
|
||||
|
||||
// valuesFromHeader returns a functions that extracts values from the request header.
|
||||
// valuePrefix is parameter to remove first part (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 remove is `<auth-scheme> `
|
||||
// note the space at the end. In case of basic authentication `Authorization: Basic <credentials>` prefix we want to remove
|
||||
// is `Basic `. In case of JWT tokens `Authorization: Bearer <token>` prefix is `Bearer `.
|
||||
// If prefix is left empty the whole value is returned.
|
||||
func valuesFromHeader(header string, valuePrefix string) ValuesExtractor {
|
||||
prefixLen := len(valuePrefix)
|
||||
// standard library parses http.Request header keys in canonical form but we may provide something else so fix this
|
||||
header = textproto.CanonicalMIMEHeaderKey(header)
|
||||
return func(c echo.Context) ([]string, error) {
|
||||
values := c.Request().Header.Values(header)
|
||||
if len(values) == 0 {
|
||||
return nil, errHeaderExtractorValueMissing
|
||||
}
|
||||
|
||||
result := make([]string, 0)
|
||||
for i, value := range values {
|
||||
if prefixLen == 0 {
|
||||
result = append(result, value)
|
||||
if i >= extractorLimit-1 {
|
||||
break
|
||||
}
|
||||
continue
|
||||
}
|
||||
if len(value) > prefixLen && strings.EqualFold(value[:prefixLen], valuePrefix) {
|
||||
result = append(result, value[prefixLen:])
|
||||
if i >= extractorLimit-1 {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(result) == 0 {
|
||||
if prefixLen > 0 {
|
||||
return nil, errHeaderExtractorValueInvalid
|
||||
}
|
||||
return nil, errHeaderExtractorValueMissing
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
}
|
||||
|
||||
// valuesFromQuery returns a function that extracts values from the query string.
|
||||
func valuesFromQuery(param string) ValuesExtractor {
|
||||
return func(c echo.Context) ([]string, error) {
|
||||
result := c.QueryParams()[param]
|
||||
if len(result) == 0 {
|
||||
return nil, errQueryExtractorValueMissing
|
||||
} else if len(result) > extractorLimit-1 {
|
||||
result = result[:extractorLimit]
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
}
|
||||
|
||||
// valuesFromParam returns a function that extracts values from the url param string.
|
||||
func valuesFromParam(param string) ValuesExtractor {
|
||||
return func(c echo.Context) ([]string, error) {
|
||||
result := make([]string, 0)
|
||||
paramVales := c.ParamValues()
|
||||
for i, p := range c.ParamNames() {
|
||||
if param == p {
|
||||
result = append(result, paramVales[i])
|
||||
if i >= extractorLimit-1 {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(result) == 0 {
|
||||
return nil, errParamExtractorValueMissing
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
}
|
||||
|
||||
// valuesFromCookie returns a function that extracts values from the named cookie.
|
||||
func valuesFromCookie(name string) ValuesExtractor {
|
||||
return func(c echo.Context) ([]string, error) {
|
||||
cookies := c.Cookies()
|
||||
if len(cookies) == 0 {
|
||||
return nil, errCookieExtractorValueMissing
|
||||
}
|
||||
|
||||
result := make([]string, 0)
|
||||
for i, cookie := range cookies {
|
||||
if name == cookie.Name {
|
||||
result = append(result, cookie.Value)
|
||||
if i >= extractorLimit-1 {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(result) == 0 {
|
||||
return nil, errCookieExtractorValueMissing
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
}
|
||||
|
||||
// valuesFromForm returns a function that extracts values from the form field.
|
||||
func valuesFromForm(name string) ValuesExtractor {
|
||||
return func(c echo.Context) ([]string, error) {
|
||||
if parseErr := c.Request().ParseForm(); parseErr != nil {
|
||||
return nil, fmt.Errorf("valuesFromForm parse form failed: %w", parseErr)
|
||||
}
|
||||
values := c.Request().Form[name]
|
||||
if len(values) == 0 {
|
||||
return nil, errFormExtractorValueMissing
|
||||
}
|
||||
if len(values) > extractorLimit-1 {
|
||||
values = values[:extractorLimit]
|
||||
}
|
||||
result := append([]string{}, values...)
|
||||
return result, nil
|
||||
}
|
||||
}
|
||||
211
vendor/github.com/labstack/echo/v4/middleware/jwt.go
generated
vendored
211
vendor/github.com/labstack/echo/v4/middleware/jwt.go
generated
vendored
@@ -1,3 +1,4 @@
|
||||
//go:build go1.15
|
||||
// +build go1.15
|
||||
|
||||
package middleware
|
||||
@@ -5,12 +6,10 @@ package middleware
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/golang-jwt/jwt"
|
||||
"github.com/labstack/echo/v4"
|
||||
"net/http"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
type (
|
||||
@@ -22,7 +21,8 @@ type (
|
||||
// BeforeFunc defines a function which is executed just before the middleware.
|
||||
BeforeFunc BeforeFunc
|
||||
|
||||
// SuccessHandler defines a function which is executed for a valid token.
|
||||
// SuccessHandler defines a function which is executed for a valid token before middleware chain continues with next
|
||||
// middleware or handler.
|
||||
SuccessHandler JWTSuccessHandler
|
||||
|
||||
// ErrorHandler defines a function which is executed for an invalid token.
|
||||
@@ -32,6 +32,13 @@ type (
|
||||
// ErrorHandlerWithContext is almost identical to ErrorHandler, but it's passed the current context.
|
||||
ErrorHandlerWithContext JWTErrorHandlerWithContext
|
||||
|
||||
// ContinueOnIgnoredError allows the next middleware/handler to be called when ErrorHandlerWithContext decides to
|
||||
// ignore the error (by returning `nil`).
|
||||
// This is useful when parts of your site/api allow public access and some authorized routes provide extra functionality.
|
||||
// In that case you can use ErrorHandlerWithContext to set a default public JWT token value in the request context
|
||||
// and continue. Some logic down the remaining execution chain needs to check that (public) token value then.
|
||||
ContinueOnIgnoredError bool
|
||||
|
||||
// Signing key to validate token.
|
||||
// This is one of the three options to provide a token validation key.
|
||||
// The order of precedence is a user-defined KeyFunc, SigningKeys and SigningKey.
|
||||
@@ -61,16 +68,26 @@ type (
|
||||
// to extract token from the request.
|
||||
// Optional. Default value "header:Authorization".
|
||||
// Possible values:
|
||||
// - "header:<name>"
|
||||
// - "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 JWT tokens `Authorization: Bearer <token>` prefix we cut is `Bearer `.
|
||||
// If prefix is left empty the whole value is returned.
|
||||
// - "query:<name>"
|
||||
// - "param:<name>"
|
||||
// - "cookie:<name>"
|
||||
// - "form:<name>"
|
||||
// Multiply sources example:
|
||||
// - "header: Authorization,cookie: myowncookie"
|
||||
|
||||
// Multiple sources example:
|
||||
// - "header:Authorization,cookie:myowncookie"
|
||||
TokenLookup string
|
||||
|
||||
// TokenLookupFuncs defines a list of user-defined functions that extract JWT token from the given context.
|
||||
// This is one of the two options to provide a token extractor.
|
||||
// The order of precedence is user-defined TokenLookupFuncs, and TokenLookup.
|
||||
// You can also provide both if you want.
|
||||
TokenLookupFuncs []ValuesExtractor
|
||||
|
||||
// AuthScheme to be used in the Authorization header.
|
||||
// Optional. Default value "Bearer".
|
||||
AuthScheme string
|
||||
@@ -95,15 +112,13 @@ type (
|
||||
}
|
||||
|
||||
// JWTSuccessHandler defines a function which is executed for a valid token.
|
||||
JWTSuccessHandler func(echo.Context)
|
||||
JWTSuccessHandler func(c echo.Context)
|
||||
|
||||
// JWTErrorHandler defines a function which is executed for an invalid token.
|
||||
JWTErrorHandler func(error) error
|
||||
JWTErrorHandler func(err error) error
|
||||
|
||||
// JWTErrorHandlerWithContext is almost identical to JWTErrorHandler, but it's passed the current context.
|
||||
JWTErrorHandlerWithContext func(error, echo.Context) error
|
||||
|
||||
jwtExtractor func(echo.Context) (string, error)
|
||||
JWTErrorHandlerWithContext func(err error, c echo.Context) error
|
||||
)
|
||||
|
||||
// Algorithms
|
||||
@@ -120,13 +135,14 @@ var (
|
||||
var (
|
||||
// DefaultJWTConfig is the default JWT auth middleware config.
|
||||
DefaultJWTConfig = JWTConfig{
|
||||
Skipper: DefaultSkipper,
|
||||
SigningMethod: AlgorithmHS256,
|
||||
ContextKey: "user",
|
||||
TokenLookup: "header:" + echo.HeaderAuthorization,
|
||||
AuthScheme: "Bearer",
|
||||
Claims: jwt.MapClaims{},
|
||||
KeyFunc: nil,
|
||||
Skipper: DefaultSkipper,
|
||||
SigningMethod: AlgorithmHS256,
|
||||
ContextKey: "user",
|
||||
TokenLookup: "header:" + echo.HeaderAuthorization,
|
||||
TokenLookupFuncs: nil,
|
||||
AuthScheme: "Bearer",
|
||||
Claims: jwt.MapClaims{},
|
||||
KeyFunc: nil,
|
||||
}
|
||||
)
|
||||
|
||||
@@ -163,7 +179,7 @@ func JWTWithConfig(config JWTConfig) echo.MiddlewareFunc {
|
||||
if config.Claims == nil {
|
||||
config.Claims = DefaultJWTConfig.Claims
|
||||
}
|
||||
if config.TokenLookup == "" {
|
||||
if config.TokenLookup == "" && len(config.TokenLookupFuncs) == 0 {
|
||||
config.TokenLookup = DefaultJWTConfig.TokenLookup
|
||||
}
|
||||
if config.AuthScheme == "" {
|
||||
@@ -176,25 +192,12 @@ func JWTWithConfig(config JWTConfig) echo.MiddlewareFunc {
|
||||
config.ParseTokenFunc = config.defaultParseToken
|
||||
}
|
||||
|
||||
// Initialize
|
||||
// Split sources
|
||||
sources := strings.Split(config.TokenLookup, ",")
|
||||
var extractors []jwtExtractor
|
||||
for _, source := range sources {
|
||||
parts := strings.Split(source, ":")
|
||||
|
||||
switch parts[0] {
|
||||
case "query":
|
||||
extractors = append(extractors, jwtFromQuery(parts[1]))
|
||||
case "param":
|
||||
extractors = append(extractors, jwtFromParam(parts[1]))
|
||||
case "cookie":
|
||||
extractors = append(extractors, jwtFromCookie(parts[1]))
|
||||
case "form":
|
||||
extractors = append(extractors, jwtFromForm(parts[1]))
|
||||
case "header":
|
||||
extractors = append(extractors, jwtFromHeader(parts[1], config.AuthScheme))
|
||||
}
|
||||
extractors, err := createExtractors(config.TokenLookup, config.AuthScheme)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if len(config.TokenLookupFuncs) > 0 {
|
||||
extractors = append(config.TokenLookupFuncs, extractors...)
|
||||
}
|
||||
|
||||
return func(next echo.HandlerFunc) echo.HandlerFunc {
|
||||
@@ -206,48 +209,54 @@ func JWTWithConfig(config JWTConfig) echo.MiddlewareFunc {
|
||||
if config.BeforeFunc != nil {
|
||||
config.BeforeFunc(c)
|
||||
}
|
||||
var auth string
|
||||
var err error
|
||||
|
||||
var lastExtractorErr error
|
||||
var lastTokenErr error
|
||||
for _, extractor := range extractors {
|
||||
// Extract token from extractor, if it's not fail break the loop and
|
||||
// set auth
|
||||
auth, err = extractor(c)
|
||||
if err == nil {
|
||||
break
|
||||
auths, err := extractor(c)
|
||||
if err != nil {
|
||||
lastExtractorErr = ErrJWTMissing // backwards compatibility: all extraction errors are same (unlike KeyAuth)
|
||||
continue
|
||||
}
|
||||
for _, auth := range auths {
|
||||
token, err := config.ParseTokenFunc(auth, c)
|
||||
if err != nil {
|
||||
lastTokenErr = err
|
||||
continue
|
||||
}
|
||||
// Store user information from token into context.
|
||||
c.Set(config.ContextKey, token)
|
||||
if config.SuccessHandler != nil {
|
||||
config.SuccessHandler(c)
|
||||
}
|
||||
return next(c)
|
||||
}
|
||||
}
|
||||
// If none of extractor has a token, handle error
|
||||
if err != nil {
|
||||
if config.ErrorHandler != nil {
|
||||
return config.ErrorHandler(err)
|
||||
}
|
||||
|
||||
if config.ErrorHandlerWithContext != nil {
|
||||
return config.ErrorHandlerWithContext(err, c)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
token, err := config.ParseTokenFunc(auth, c)
|
||||
if err == nil {
|
||||
// Store user information from token into context.
|
||||
c.Set(config.ContextKey, token)
|
||||
if config.SuccessHandler != nil {
|
||||
config.SuccessHandler(c)
|
||||
}
|
||||
return next(c)
|
||||
// we are here only when we did not successfully extract or parse any of the tokens
|
||||
err := lastTokenErr
|
||||
if err == nil { // prioritize token errors over extracting errors
|
||||
err = lastExtractorErr
|
||||
}
|
||||
if config.ErrorHandler != nil {
|
||||
return config.ErrorHandler(err)
|
||||
}
|
||||
if config.ErrorHandlerWithContext != nil {
|
||||
return config.ErrorHandlerWithContext(err, c)
|
||||
tmpErr := config.ErrorHandlerWithContext(err, c)
|
||||
if config.ContinueOnIgnoredError && tmpErr == nil {
|
||||
return next(c)
|
||||
}
|
||||
return tmpErr
|
||||
}
|
||||
return &echo.HTTPError{
|
||||
Code: ErrJWTInvalid.Code,
|
||||
Message: ErrJWTInvalid.Message,
|
||||
Internal: err,
|
||||
|
||||
// backwards compatible errors codes
|
||||
if lastTokenErr != nil {
|
||||
return &echo.HTTPError{
|
||||
Code: ErrJWTInvalid.Code,
|
||||
Message: ErrJWTInvalid.Message,
|
||||
Internal: err,
|
||||
}
|
||||
}
|
||||
return err // this is lastExtractorErr value
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -289,59 +298,3 @@ func (config *JWTConfig) defaultKeyFunc(t *jwt.Token) (interface{}, error) {
|
||||
|
||||
return config.SigningKey, nil
|
||||
}
|
||||
|
||||
// jwtFromHeader returns a `jwtExtractor` that extracts token from the request header.
|
||||
func jwtFromHeader(header string, authScheme string) jwtExtractor {
|
||||
return func(c echo.Context) (string, error) {
|
||||
auth := c.Request().Header.Get(header)
|
||||
l := len(authScheme)
|
||||
if len(auth) > l+1 && strings.EqualFold(auth[:l], authScheme) {
|
||||
return auth[l+1:], nil
|
||||
}
|
||||
return "", ErrJWTMissing
|
||||
}
|
||||
}
|
||||
|
||||
// jwtFromQuery returns a `jwtExtractor` that extracts token from the query string.
|
||||
func jwtFromQuery(param string) jwtExtractor {
|
||||
return func(c echo.Context) (string, error) {
|
||||
token := c.QueryParam(param)
|
||||
if token == "" {
|
||||
return "", ErrJWTMissing
|
||||
}
|
||||
return token, nil
|
||||
}
|
||||
}
|
||||
|
||||
// jwtFromParam returns a `jwtExtractor` that extracts token from the url param string.
|
||||
func jwtFromParam(param string) jwtExtractor {
|
||||
return func(c echo.Context) (string, error) {
|
||||
token := c.Param(param)
|
||||
if token == "" {
|
||||
return "", ErrJWTMissing
|
||||
}
|
||||
return token, nil
|
||||
}
|
||||
}
|
||||
|
||||
// jwtFromCookie returns a `jwtExtractor` that extracts token from the named cookie.
|
||||
func jwtFromCookie(name string) jwtExtractor {
|
||||
return func(c echo.Context) (string, error) {
|
||||
cookie, err := c.Cookie(name)
|
||||
if err != nil {
|
||||
return "", ErrJWTMissing
|
||||
}
|
||||
return cookie.Value, nil
|
||||
}
|
||||
}
|
||||
|
||||
// jwtFromForm returns a `jwtExtractor` that extracts token from the form field.
|
||||
func jwtFromForm(name string) jwtExtractor {
|
||||
return func(c echo.Context) (string, error) {
|
||||
field := c.FormValue(name)
|
||||
if field == "" {
|
||||
return "", ErrJWTMissing
|
||||
}
|
||||
return field, nil
|
||||
}
|
||||
}
|
||||
|
||||
173
vendor/github.com/labstack/echo/v4/middleware/key_auth.go
generated
vendored
173
vendor/github.com/labstack/echo/v4/middleware/key_auth.go
generated
vendored
@@ -2,11 +2,8 @@ package middleware
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type (
|
||||
@@ -15,15 +12,21 @@ type (
|
||||
// Skipper defines a function to skip middleware.
|
||||
Skipper Skipper
|
||||
|
||||
// KeyLookup is a string in the form of "<source>:<name>" that is used
|
||||
// KeyLookup is a string in the form of "<source>:<name>" or "<source>:<name>,<source>:<name>" that is used
|
||||
// to extract key from the request.
|
||||
// Optional. Default value "header:Authorization".
|
||||
// Possible values:
|
||||
// - "header:<name>"
|
||||
// - "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>"
|
||||
// - "form:<name>"
|
||||
// - "cookie:<name>"
|
||||
KeyLookup string `yaml:"key_lookup"`
|
||||
// Multiple sources example:
|
||||
// - "header:Authorization,header:X-Api-Key"
|
||||
KeyLookup string
|
||||
|
||||
// AuthScheme to be used in the Authorization header.
|
||||
// Optional. Default value "Bearer".
|
||||
@@ -36,15 +39,20 @@ type (
|
||||
// ErrorHandler defines a function which is executed for an invalid key.
|
||||
// It may be used to define a custom error.
|
||||
ErrorHandler KeyAuthErrorHandler
|
||||
|
||||
// ContinueOnIgnoredError allows the next middleware/handler to be called when ErrorHandler decides to
|
||||
// ignore the error (by returning `nil`).
|
||||
// This is useful when parts of your site/api allow public access and some authorized routes provide extra functionality.
|
||||
// In that case you can use ErrorHandler to set a default public key auth value in the request context
|
||||
// and continue. Some logic down the remaining execution chain needs to check that (public) key auth value then.
|
||||
ContinueOnIgnoredError bool
|
||||
}
|
||||
|
||||
// KeyAuthValidator defines a function to validate KeyAuth credentials.
|
||||
KeyAuthValidator func(string, echo.Context) (bool, error)
|
||||
|
||||
keyExtractor func(echo.Context) (string, error)
|
||||
KeyAuthValidator func(auth string, c echo.Context) (bool, error)
|
||||
|
||||
// KeyAuthErrorHandler defines a function which is executed for an invalid key.
|
||||
KeyAuthErrorHandler func(error, echo.Context) error
|
||||
KeyAuthErrorHandler func(err error, c echo.Context) error
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -56,6 +64,21 @@ var (
|
||||
}
|
||||
)
|
||||
|
||||
// ErrKeyAuthMissing is error type when KeyAuth middleware is unable to extract value from lookups
|
||||
type ErrKeyAuthMissing struct {
|
||||
Err error
|
||||
}
|
||||
|
||||
// Error returns errors text
|
||||
func (e *ErrKeyAuthMissing) Error() string {
|
||||
return e.Err.Error()
|
||||
}
|
||||
|
||||
// Unwrap unwraps error
|
||||
func (e *ErrKeyAuthMissing) Unwrap() error {
|
||||
return e.Err
|
||||
}
|
||||
|
||||
// KeyAuth returns an KeyAuth middleware.
|
||||
//
|
||||
// For valid key it calls the next handler.
|
||||
@@ -85,16 +108,9 @@ func KeyAuthWithConfig(config KeyAuthConfig) echo.MiddlewareFunc {
|
||||
panic("echo: key-auth middleware requires a validator function")
|
||||
}
|
||||
|
||||
// Initialize
|
||||
parts := strings.Split(config.KeyLookup, ":")
|
||||
extractor := keyFromHeader(parts[1], config.AuthScheme)
|
||||
switch parts[0] {
|
||||
case "query":
|
||||
extractor = keyFromQuery(parts[1])
|
||||
case "form":
|
||||
extractor = keyFromForm(parts[1])
|
||||
case "cookie":
|
||||
extractor = keyFromCookie(parts[1])
|
||||
extractors, err := createExtractors(config.KeyLookup, config.AuthScheme)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return func(next echo.HandlerFunc) echo.HandlerFunc {
|
||||
@@ -103,79 +119,62 @@ func KeyAuthWithConfig(config KeyAuthConfig) echo.MiddlewareFunc {
|
||||
return next(c)
|
||||
}
|
||||
|
||||
// Extract and verify key
|
||||
key, err := extractor(c)
|
||||
if err != nil {
|
||||
if config.ErrorHandler != nil {
|
||||
return config.ErrorHandler(err, c)
|
||||
var lastExtractorErr error
|
||||
var lastValidatorErr error
|
||||
for _, extractor := range extractors {
|
||||
keys, err := extractor(c)
|
||||
if err != nil {
|
||||
lastExtractorErr = err
|
||||
continue
|
||||
}
|
||||
for _, key := range keys {
|
||||
valid, err := config.Validator(key, c)
|
||||
if err != nil {
|
||||
lastValidatorErr = err
|
||||
continue
|
||||
}
|
||||
if valid {
|
||||
return next(c)
|
||||
}
|
||||
lastValidatorErr = errors.New("invalid key")
|
||||
}
|
||||
return echo.NewHTTPError(http.StatusBadRequest, err.Error())
|
||||
}
|
||||
valid, err := config.Validator(key, c)
|
||||
if err != nil {
|
||||
if config.ErrorHandler != nil {
|
||||
return config.ErrorHandler(err, c)
|
||||
|
||||
// we are here only when we did not successfully extract and validate any of keys
|
||||
err := lastValidatorErr
|
||||
if err == nil { // prioritize validator errors over extracting errors
|
||||
// ugly part to preserve backwards compatible errors. someone could rely on them
|
||||
if lastExtractorErr == errQueryExtractorValueMissing {
|
||||
err = errors.New("missing key in the query string")
|
||||
} else if lastExtractorErr == errCookieExtractorValueMissing {
|
||||
err = errors.New("missing key in cookies")
|
||||
} else if lastExtractorErr == errFormExtractorValueMissing {
|
||||
err = errors.New("missing key in the form")
|
||||
} else if lastExtractorErr == errHeaderExtractorValueMissing {
|
||||
err = errors.New("missing key in request header")
|
||||
} else if lastExtractorErr == errHeaderExtractorValueInvalid {
|
||||
err = errors.New("invalid key in the request header")
|
||||
} else {
|
||||
err = lastExtractorErr
|
||||
}
|
||||
err = &ErrKeyAuthMissing{Err: err}
|
||||
}
|
||||
|
||||
if config.ErrorHandler != nil {
|
||||
tmpErr := config.ErrorHandler(err, c)
|
||||
if config.ContinueOnIgnoredError && tmpErr == nil {
|
||||
return next(c)
|
||||
}
|
||||
return tmpErr
|
||||
}
|
||||
if lastValidatorErr != nil { // prioritize validator errors over extracting errors
|
||||
return &echo.HTTPError{
|
||||
Code: http.StatusUnauthorized,
|
||||
Message: "invalid key",
|
||||
Internal: err,
|
||||
Message: "Unauthorized",
|
||||
Internal: lastValidatorErr,
|
||||
}
|
||||
} else if valid {
|
||||
return next(c)
|
||||
}
|
||||
return echo.ErrUnauthorized
|
||||
return echo.NewHTTPError(http.StatusBadRequest, err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// keyFromHeader returns a `keyExtractor` that extracts key from the request header.
|
||||
func keyFromHeader(header string, authScheme string) keyExtractor {
|
||||
return func(c echo.Context) (string, error) {
|
||||
auth := c.Request().Header.Get(header)
|
||||
if auth == "" {
|
||||
return "", errors.New("missing key in request header")
|
||||
}
|
||||
if header == echo.HeaderAuthorization {
|
||||
l := len(authScheme)
|
||||
if len(auth) > l+1 && auth[:l] == authScheme {
|
||||
return auth[l+1:], nil
|
||||
}
|
||||
return "", errors.New("invalid key in the request header")
|
||||
}
|
||||
return auth, nil
|
||||
}
|
||||
}
|
||||
|
||||
// keyFromQuery returns a `keyExtractor` that extracts key from the query string.
|
||||
func keyFromQuery(param string) keyExtractor {
|
||||
return func(c echo.Context) (string, error) {
|
||||
key := c.QueryParam(param)
|
||||
if key == "" {
|
||||
return "", errors.New("missing key in the query string")
|
||||
}
|
||||
return key, nil
|
||||
}
|
||||
}
|
||||
|
||||
// keyFromForm returns a `keyExtractor` that extracts key from the form.
|
||||
func keyFromForm(param string) keyExtractor {
|
||||
return func(c echo.Context) (string, error) {
|
||||
key := c.FormValue(param)
|
||||
if key == "" {
|
||||
return "", errors.New("missing key in the form")
|
||||
}
|
||||
return key, nil
|
||||
}
|
||||
}
|
||||
|
||||
// keyFromCookie returns a `keyExtractor` that extracts key from the form.
|
||||
func keyFromCookie(cookieName string) keyExtractor {
|
||||
return func(c echo.Context) (string, error) {
|
||||
key, err := c.Cookie(cookieName)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("missing key in cookies: %w", err)
|
||||
}
|
||||
return key.Value, nil
|
||||
}
|
||||
}
|
||||
|
||||
4
vendor/github.com/labstack/echo/v4/middleware/middleware.go
generated
vendored
4
vendor/github.com/labstack/echo/v4/middleware/middleware.go
generated
vendored
@@ -12,10 +12,10 @@ import (
|
||||
type (
|
||||
// Skipper defines a function to skip middleware. Returning true skips processing
|
||||
// the middleware.
|
||||
Skipper func(echo.Context) bool
|
||||
Skipper func(c echo.Context) bool
|
||||
|
||||
// BeforeFunc defines a function which is executed just before the middleware.
|
||||
BeforeFunc func(echo.Context)
|
||||
BeforeFunc func(c echo.Context)
|
||||
)
|
||||
|
||||
func captureTokens(pattern *regexp.Regexp, input string) *strings.Replacer {
|
||||
|
||||
21
vendor/github.com/labstack/echo/v4/middleware/recover.go
generated
vendored
21
vendor/github.com/labstack/echo/v4/middleware/recover.go
generated
vendored
@@ -9,6 +9,9 @@ import (
|
||||
)
|
||||
|
||||
type (
|
||||
// LogErrorFunc defines a function for custom logging in the middleware.
|
||||
LogErrorFunc func(c echo.Context, err error, stack []byte) error
|
||||
|
||||
// RecoverConfig defines the config for Recover middleware.
|
||||
RecoverConfig struct {
|
||||
// Skipper defines a function to skip middleware.
|
||||
@@ -30,6 +33,10 @@ type (
|
||||
// LogLevel is log level to printing stack trace.
|
||||
// Optional. Default value 0 (Print).
|
||||
LogLevel log.Lvl
|
||||
|
||||
// LogErrorFunc defines a function for custom logging in the middleware.
|
||||
// If it's set you don't need to provide LogLevel for config.
|
||||
LogErrorFunc LogErrorFunc
|
||||
}
|
||||
)
|
||||
|
||||
@@ -41,6 +48,7 @@ var (
|
||||
DisableStackAll: false,
|
||||
DisablePrintStack: false,
|
||||
LogLevel: 0,
|
||||
LogErrorFunc: nil,
|
||||
}
|
||||
)
|
||||
|
||||
@@ -73,9 +81,18 @@ func RecoverWithConfig(config RecoverConfig) echo.MiddlewareFunc {
|
||||
if !ok {
|
||||
err = fmt.Errorf("%v", r)
|
||||
}
|
||||
stack := make([]byte, config.StackSize)
|
||||
length := runtime.Stack(stack, !config.DisableStackAll)
|
||||
var stack []byte
|
||||
var length int
|
||||
|
||||
if !config.DisablePrintStack {
|
||||
stack = make([]byte, config.StackSize)
|
||||
length = runtime.Stack(stack, !config.DisableStackAll)
|
||||
stack = stack[:length]
|
||||
}
|
||||
|
||||
if config.LogErrorFunc != nil {
|
||||
err = config.LogErrorFunc(c, err, stack)
|
||||
} else if !config.DisablePrintStack {
|
||||
msg := fmt.Sprintf("[PANIC RECOVER] %v %s\n", err, stack[:length])
|
||||
switch config.LogLevel {
|
||||
case log.DEBUG:
|
||||
|
||||
95
vendor/github.com/labstack/echo/v4/router.go
generated
vendored
95
vendor/github.com/labstack/echo/v4/router.go
generated
vendored
@@ -1,6 +1,7 @@
|
||||
package echo
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
@@ -31,17 +32,18 @@ type (
|
||||
kind uint8
|
||||
children []*node
|
||||
methodHandler struct {
|
||||
connect HandlerFunc
|
||||
delete HandlerFunc
|
||||
get HandlerFunc
|
||||
head HandlerFunc
|
||||
options HandlerFunc
|
||||
patch HandlerFunc
|
||||
post HandlerFunc
|
||||
propfind HandlerFunc
|
||||
put HandlerFunc
|
||||
trace HandlerFunc
|
||||
report HandlerFunc
|
||||
connect HandlerFunc
|
||||
delete HandlerFunc
|
||||
get HandlerFunc
|
||||
head HandlerFunc
|
||||
options HandlerFunc
|
||||
patch HandlerFunc
|
||||
post HandlerFunc
|
||||
propfind HandlerFunc
|
||||
put HandlerFunc
|
||||
trace HandlerFunc
|
||||
report HandlerFunc
|
||||
allowHeader string
|
||||
}
|
||||
)
|
||||
|
||||
@@ -68,6 +70,51 @@ func (m *methodHandler) isHandler() bool {
|
||||
m.report != nil
|
||||
}
|
||||
|
||||
func (m *methodHandler) updateAllowHeader() {
|
||||
buf := new(bytes.Buffer)
|
||||
buf.WriteString(http.MethodOptions)
|
||||
|
||||
if m.connect != nil {
|
||||
buf.WriteString(", ")
|
||||
buf.WriteString(http.MethodConnect)
|
||||
}
|
||||
if m.delete != nil {
|
||||
buf.WriteString(", ")
|
||||
buf.WriteString(http.MethodDelete)
|
||||
}
|
||||
if m.get != nil {
|
||||
buf.WriteString(", ")
|
||||
buf.WriteString(http.MethodGet)
|
||||
}
|
||||
if m.head != nil {
|
||||
buf.WriteString(", ")
|
||||
buf.WriteString(http.MethodHead)
|
||||
}
|
||||
if m.patch != nil {
|
||||
buf.WriteString(", ")
|
||||
buf.WriteString(http.MethodPatch)
|
||||
}
|
||||
if m.post != nil {
|
||||
buf.WriteString(", ")
|
||||
buf.WriteString(http.MethodPost)
|
||||
}
|
||||
if m.propfind != nil {
|
||||
buf.WriteString(", PROPFIND")
|
||||
}
|
||||
if m.put != nil {
|
||||
buf.WriteString(", ")
|
||||
buf.WriteString(http.MethodPut)
|
||||
}
|
||||
if m.trace != nil {
|
||||
buf.WriteString(", ")
|
||||
buf.WriteString(http.MethodTrace)
|
||||
}
|
||||
if m.report != nil {
|
||||
buf.WriteString(", REPORT")
|
||||
}
|
||||
m.allowHeader = buf.String()
|
||||
}
|
||||
|
||||
// NewRouter returns a new Router instance.
|
||||
func NewRouter(e *Echo) *Router {
|
||||
return &Router{
|
||||
@@ -326,6 +373,7 @@ func (n *node) addHandler(method string, h HandlerFunc) {
|
||||
n.methodHandler.report = h
|
||||
}
|
||||
|
||||
n.methodHandler.updateAllowHeader()
|
||||
if h != nil {
|
||||
n.isHandler = true
|
||||
} else {
|
||||
@@ -362,13 +410,14 @@ func (n *node) findHandler(method string) HandlerFunc {
|
||||
}
|
||||
}
|
||||
|
||||
func (n *node) checkMethodNotAllowed() HandlerFunc {
|
||||
for _, m := range methods {
|
||||
if h := n.findHandler(m); h != nil {
|
||||
return MethodNotAllowedHandler
|
||||
}
|
||||
func optionsMethodHandler(allowMethods string) func(c Context) error {
|
||||
return func(c Context) error {
|
||||
// Note: we are not handling most of the CORS headers here. CORS is handled by CORS middleware
|
||||
// 'OPTIONS' method RFC: https://httpwg.org/specs/rfc7231.html#OPTIONS
|
||||
// 'Allow' header RFC: https://datatracker.ietf.org/doc/html/rfc7231#section-7.4.1
|
||||
c.Response().Header().Add(HeaderAllow, allowMethods)
|
||||
return c.NoContent(http.StatusNoContent)
|
||||
}
|
||||
return NotFoundHandler
|
||||
}
|
||||
|
||||
// Find lookup a handler registered for method and path. It also parses URL for path
|
||||
@@ -563,10 +612,16 @@ func (r *Router) Find(method, path string, c Context) {
|
||||
// use previous match as basis. although we have no matching handler we have path match.
|
||||
// so we can send http.StatusMethodNotAllowed (405) instead of http.StatusNotFound (404)
|
||||
currentNode = previousBestMatchNode
|
||||
ctx.handler = currentNode.checkMethodNotAllowed()
|
||||
|
||||
ctx.handler = NotFoundHandler
|
||||
if currentNode.isHandler {
|
||||
ctx.Set(ContextKeyHeaderAllow, currentNode.methodHandler.allowHeader)
|
||||
ctx.handler = MethodNotAllowedHandler
|
||||
if method == http.MethodOptions {
|
||||
ctx.handler = optionsMethodHandler(currentNode.methodHandler.allowHeader)
|
||||
}
|
||||
}
|
||||
}
|
||||
ctx.path = currentNode.ppath
|
||||
ctx.pnames = currentNode.pnames
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
2
vendor/github.com/matterbridge/discordgo/.gitignore
generated
vendored
2
vendor/github.com/matterbridge/discordgo/.gitignore
generated
vendored
@@ -1,2 +0,0 @@
|
||||
# IDE-specific metadata
|
||||
.idea/
|
||||
161
vendor/github.com/matterbridge/discordgo/discord.go
generated
vendored
161
vendor/github.com/matterbridge/discordgo/discord.go
generated
vendored
@@ -1,161 +0,0 @@
|
||||
// Discordgo - Discord bindings for Go
|
||||
// Available at https://github.com/matterbridge/discordgo
|
||||
|
||||
// Copyright 2015-2016 Bruce Marriner <bruce@sqls.net>. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This file contains high level helper functions and easy entry points for the
|
||||
// entire discordgo package. These functions are being developed and are very
|
||||
// experimental at this point. They will most likely change so please use the
|
||||
// low level functions if that's a problem.
|
||||
|
||||
// Package discordgo provides Discord binding for Go
|
||||
package discordgo
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"runtime"
|
||||
"time"
|
||||
)
|
||||
|
||||
// VERSION of DiscordGo, follows Semantic Versioning. (http://semver.org/)
|
||||
const VERSION = "0.23.0"
|
||||
|
||||
// ErrMFA will be risen by New when the user has 2FA.
|
||||
var ErrMFA = errors.New("account has 2FA enabled")
|
||||
|
||||
// New creates a new Discord session and will automate some startup
|
||||
// tasks if given enough information to do so. Currently you can pass zero
|
||||
// arguments and it will return an empty Discord session.
|
||||
// There are 3 ways to call New:
|
||||
// With a single auth token - All requests will use the token blindly
|
||||
// (just tossing it into the HTTP Authorization header);
|
||||
// no verification of the token will be done and requests may fail.
|
||||
// IF THE TOKEN IS FOR A BOT, IT MUST BE PREFIXED WITH `BOT `
|
||||
// eg: `"Bot <token>"`
|
||||
// IF IT IS AN OAUTH2 ACCESS TOKEN, IT MUST BE PREFIXED WITH `Bearer `
|
||||
// eg: `"Bearer <token>"`
|
||||
// With an email and password - Discord will sign in with the provided
|
||||
// credentials.
|
||||
// With an email, password and auth token - Discord will verify the auth
|
||||
// token, if it is invalid it will sign in with the provided
|
||||
// credentials. This is the Discord recommended way to sign in.
|
||||
//
|
||||
// NOTE: While email/pass authentication is supported by DiscordGo it is
|
||||
// HIGHLY DISCOURAGED by Discord. Please only use email/pass to obtain a token
|
||||
// and then use that authentication token for all future connections.
|
||||
// Also, doing any form of automation with a user (non Bot) account may result
|
||||
// in that account being permanently banned from Discord.
|
||||
func New(args ...interface{}) (s *Session, err error) {
|
||||
|
||||
// Create an empty Session interface.
|
||||
s = &Session{
|
||||
State: NewState(),
|
||||
Ratelimiter: NewRatelimiter(),
|
||||
StateEnabled: true,
|
||||
Compress: true,
|
||||
ShouldReconnectOnError: true,
|
||||
ShardID: 0,
|
||||
ShardCount: 1,
|
||||
MaxRestRetries: 3,
|
||||
Client: &http.Client{Timeout: (20 * time.Second)},
|
||||
UserAgent: "DiscordBot (https://github.com/matterbridge/discordgo, v" + VERSION + ")",
|
||||
sequence: new(int64),
|
||||
LastHeartbeatAck: time.Now().UTC(),
|
||||
}
|
||||
|
||||
// Initilize the Identify Package with defaults
|
||||
// These can be modified prior to calling Open()
|
||||
s.Identify.Compress = true
|
||||
s.Identify.LargeThreshold = 250
|
||||
s.Identify.GuildSubscriptions = true
|
||||
s.Identify.Properties.OS = runtime.GOOS
|
||||
s.Identify.Properties.Browser = "DiscordGo v" + VERSION
|
||||
s.Identify.Intents = MakeIntent(IntentsAllWithoutPrivileged)
|
||||
|
||||
// If no arguments are passed return the empty Session interface.
|
||||
if args == nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Variables used below when parsing func arguments
|
||||
var auth, pass string
|
||||
|
||||
// Parse passed arguments
|
||||
for _, arg := range args {
|
||||
|
||||
switch v := arg.(type) {
|
||||
|
||||
case []string:
|
||||
if len(v) > 3 {
|
||||
err = fmt.Errorf("too many string parameters provided")
|
||||
return
|
||||
}
|
||||
|
||||
// First string is either token or username
|
||||
if len(v) > 0 {
|
||||
auth = v[0]
|
||||
}
|
||||
|
||||
// If second string exists, it must be a password.
|
||||
if len(v) > 1 {
|
||||
pass = v[1]
|
||||
}
|
||||
|
||||
// If third string exists, it must be an auth token.
|
||||
if len(v) > 2 {
|
||||
s.Identify.Token = v[2]
|
||||
s.Token = v[2] // TODO: Remove, Deprecated - Kept for backwards compatibility.
|
||||
}
|
||||
|
||||
case string:
|
||||
// First string must be either auth token or username.
|
||||
// Second string must be a password.
|
||||
// Only 2 input strings are supported.
|
||||
|
||||
if auth == "" {
|
||||
auth = v
|
||||
} else if pass == "" {
|
||||
pass = v
|
||||
} else if s.Token == "" {
|
||||
s.Identify.Token = v
|
||||
s.Token = v // TODO: Remove, Deprecated - Kept for backwards compatibility.
|
||||
} else {
|
||||
err = fmt.Errorf("too many string parameters provided")
|
||||
return
|
||||
}
|
||||
|
||||
// case Config:
|
||||
// TODO: Parse configuration struct
|
||||
|
||||
default:
|
||||
err = fmt.Errorf("unsupported parameter type provided")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// If only one string was provided, assume it is an auth token.
|
||||
// Otherwise get auth token from Discord, if a token was specified
|
||||
// Discord will verify it for free, or log the user in if it is
|
||||
// invalid.
|
||||
if pass == "" {
|
||||
s.Identify.Token = auth
|
||||
s.Token = auth // TODO: Remove, Deprecated - Kept for backwards compatibility.
|
||||
} else {
|
||||
err = s.Login(auth, pass)
|
||||
// TODO: Remove last s.Token part, Deprecated - Kept for backwards compatibility.
|
||||
if err != nil || s.Identify.Token == "" || s.Token == "" {
|
||||
if s.MFA {
|
||||
err = ErrMFA
|
||||
} else {
|
||||
err = fmt.Errorf("Unable to fetch discord authentication token. %v", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
153
vendor/github.com/matterbridge/discordgo/endpoints.go
generated
vendored
153
vendor/github.com/matterbridge/discordgo/endpoints.go
generated
vendored
@@ -1,153 +0,0 @@
|
||||
// Discordgo - Discord bindings for Go
|
||||
// Available at https://github.com/bwmarrin/discordgo
|
||||
|
||||
// Copyright 2015-2016 Bruce Marriner <bruce@sqls.net>. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This file contains variables for all known Discord end points. All functions
|
||||
// throughout the Discordgo package use these variables for all connections
|
||||
// to Discord. These are all exported and you may modify them if needed.
|
||||
|
||||
package discordgo
|
||||
|
||||
import "strconv"
|
||||
|
||||
// APIVersion is the Discord API version used for the REST and Websocket API.
|
||||
var APIVersion = "8"
|
||||
|
||||
// Known Discord API Endpoints.
|
||||
var (
|
||||
EndpointStatus = "https://status.discord.com/api/v2/"
|
||||
EndpointSm = EndpointStatus + "scheduled-maintenances/"
|
||||
EndpointSmActive = EndpointSm + "active.json"
|
||||
EndpointSmUpcoming = EndpointSm + "upcoming.json"
|
||||
|
||||
EndpointDiscord = "https://discord.com/"
|
||||
EndpointAPI = EndpointDiscord + "api/v" + APIVersion + "/"
|
||||
EndpointGuilds = EndpointAPI + "guilds/"
|
||||
EndpointChannels = EndpointAPI + "channels/"
|
||||
EndpointUsers = EndpointAPI + "users/"
|
||||
EndpointGateway = EndpointAPI + "gateway"
|
||||
EndpointGatewayBot = EndpointGateway + "/bot"
|
||||
EndpointWebhooks = EndpointAPI + "webhooks/"
|
||||
|
||||
EndpointCDN = "https://cdn.discordapp.com/"
|
||||
EndpointCDNAttachments = EndpointCDN + "attachments/"
|
||||
EndpointCDNAvatars = EndpointCDN + "avatars/"
|
||||
EndpointCDNIcons = EndpointCDN + "icons/"
|
||||
EndpointCDNSplashes = EndpointCDN + "splashes/"
|
||||
EndpointCDNChannelIcons = EndpointCDN + "channel-icons/"
|
||||
EndpointCDNBanners = EndpointCDN + "banners/"
|
||||
|
||||
EndpointAuth = EndpointAPI + "auth/"
|
||||
EndpointLogin = EndpointAuth + "login"
|
||||
EndpointLogout = EndpointAuth + "logout"
|
||||
EndpointVerify = EndpointAuth + "verify"
|
||||
EndpointVerifyResend = EndpointAuth + "verify/resend"
|
||||
EndpointForgotPassword = EndpointAuth + "forgot"
|
||||
EndpointResetPassword = EndpointAuth + "reset"
|
||||
EndpointRegister = EndpointAuth + "register"
|
||||
|
||||
EndpointVoice = EndpointAPI + "/voice/"
|
||||
EndpointVoiceRegions = EndpointVoice + "regions"
|
||||
EndpointVoiceIce = EndpointVoice + "ice"
|
||||
|
||||
EndpointTutorial = EndpointAPI + "tutorial/"
|
||||
EndpointTutorialIndicators = EndpointTutorial + "indicators"
|
||||
|
||||
EndpointTrack = EndpointAPI + "track"
|
||||
EndpointSso = EndpointAPI + "sso"
|
||||
EndpointReport = EndpointAPI + "report"
|
||||
EndpointIntegrations = EndpointAPI + "integrations"
|
||||
|
||||
EndpointUser = func(uID string) string { return EndpointUsers + uID }
|
||||
EndpointUserAvatar = func(uID, aID string) string { return EndpointCDNAvatars + uID + "/" + aID + ".png" }
|
||||
EndpointUserAvatarAnimated = func(uID, aID string) string { return EndpointCDNAvatars + uID + "/" + aID + ".gif" }
|
||||
EndpointDefaultUserAvatar = func(uDiscriminator string) string {
|
||||
uDiscriminatorInt, _ := strconv.Atoi(uDiscriminator)
|
||||
return EndpointCDN + "embed/avatars/" + strconv.Itoa(uDiscriminatorInt%5) + ".png"
|
||||
}
|
||||
EndpointUserSettings = func(uID string) string { return EndpointUsers + uID + "/settings" }
|
||||
EndpointUserGuilds = func(uID string) string { return EndpointUsers + uID + "/guilds" }
|
||||
EndpointUserGuild = func(uID, gID string) string { return EndpointUsers + uID + "/guilds/" + gID }
|
||||
EndpointUserGuildSettings = func(uID, gID string) string { return EndpointUsers + uID + "/guilds/" + gID + "/settings" }
|
||||
EndpointUserChannels = func(uID string) string { return EndpointUsers + uID + "/channels" }
|
||||
EndpointUserDevices = func(uID string) string { return EndpointUsers + uID + "/devices" }
|
||||
EndpointUserConnections = func(uID string) string { return EndpointUsers + uID + "/connections" }
|
||||
EndpointUserNotes = func(uID string) string { return EndpointUsers + "@me/notes/" + uID }
|
||||
|
||||
EndpointGuild = func(gID string) string { return EndpointGuilds + gID }
|
||||
EndpointGuildChannels = func(gID string) string { return EndpointGuilds + gID + "/channels" }
|
||||
EndpointGuildMembers = func(gID string) string { return EndpointGuilds + gID + "/members" }
|
||||
EndpointGuildMember = func(gID, uID string) string { return EndpointGuilds + gID + "/members/" + uID }
|
||||
EndpointGuildMemberRole = func(gID, uID, rID string) string { return EndpointGuilds + gID + "/members/" + uID + "/roles/" + rID }
|
||||
EndpointGuildBans = func(gID string) string { return EndpointGuilds + gID + "/bans" }
|
||||
EndpointGuildBan = func(gID, uID string) string { return EndpointGuilds + gID + "/bans/" + uID }
|
||||
EndpointGuildIntegrations = func(gID string) string { return EndpointGuilds + gID + "/integrations" }
|
||||
EndpointGuildIntegration = func(gID, iID string) string { return EndpointGuilds + gID + "/integrations/" + iID }
|
||||
EndpointGuildIntegrationSync = func(gID, iID string) string { return EndpointGuilds + gID + "/integrations/" + iID + "/sync" }
|
||||
EndpointGuildRoles = func(gID string) string { return EndpointGuilds + gID + "/roles" }
|
||||
EndpointGuildRole = func(gID, rID string) string { return EndpointGuilds + gID + "/roles/" + rID }
|
||||
EndpointGuildInvites = func(gID string) string { return EndpointGuilds + gID + "/invites" }
|
||||
EndpointGuildWidget = func(gID string) string { return EndpointGuilds + gID + "/widget" }
|
||||
EndpointGuildEmbed = EndpointGuildWidget
|
||||
EndpointGuildPrune = func(gID string) string { return EndpointGuilds + gID + "/prune" }
|
||||
EndpointGuildIcon = func(gID, hash string) string { return EndpointCDNIcons + gID + "/" + hash + ".png" }
|
||||
EndpointGuildIconAnimated = func(gID, hash string) string { return EndpointCDNIcons + gID + "/" + hash + ".gif" }
|
||||
EndpointGuildSplash = func(gID, hash string) string { return EndpointCDNSplashes + gID + "/" + hash + ".png" }
|
||||
EndpointGuildWebhooks = func(gID string) string { return EndpointGuilds + gID + "/webhooks" }
|
||||
EndpointGuildAuditLogs = func(gID string) string { return EndpointGuilds + gID + "/audit-logs" }
|
||||
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" }
|
||||
|
||||
EndpointChannel = func(cID string) string { return EndpointChannels + cID }
|
||||
EndpointChannelPermissions = func(cID string) string { return EndpointChannels + cID + "/permissions" }
|
||||
EndpointChannelPermission = func(cID, tID string) string { return EndpointChannels + cID + "/permissions/" + tID }
|
||||
EndpointChannelInvites = func(cID string) string { return EndpointChannels + cID + "/invites" }
|
||||
EndpointChannelTyping = func(cID string) string { return EndpointChannels + cID + "/typing" }
|
||||
EndpointChannelMessages = func(cID string) string { return EndpointChannels + cID + "/messages" }
|
||||
EndpointChannelMessage = func(cID, mID string) string { return EndpointChannels + cID + "/messages/" + mID }
|
||||
EndpointChannelMessageAck = func(cID, mID string) string { return EndpointChannels + cID + "/messages/" + mID + "/ack" }
|
||||
EndpointChannelMessagesBulkDelete = func(cID string) string { return EndpointChannel(cID) + "/messages/bulk-delete" }
|
||||
EndpointChannelMessagesPins = func(cID string) string { return EndpointChannel(cID) + "/pins" }
|
||||
EndpointChannelMessagePin = func(cID, mID string) string { return EndpointChannel(cID) + "/pins/" + mID }
|
||||
EndpointChannelMessageCrosspost = func(cID, mID string) string { return EndpointChannel(cID) + "/messages/" + mID + "/crosspost" }
|
||||
EndpointChannelFollow = func(cID string) string { return EndpointChannel(cID) + "/followers" }
|
||||
|
||||
EndpointGroupIcon = func(cID, hash string) string { return EndpointCDNChannelIcons + cID + "/" + hash + ".png" }
|
||||
|
||||
EndpointChannelWebhooks = func(cID string) string { return EndpointChannel(cID) + "/webhooks" }
|
||||
EndpointWebhook = func(wID string) string { return EndpointWebhooks + wID }
|
||||
EndpointWebhookToken = func(wID, token string) string { return EndpointWebhooks + wID + "/" + token }
|
||||
|
||||
EndpointMessageReactionsAll = func(cID, mID string) string {
|
||||
return EndpointChannelMessage(cID, mID) + "/reactions"
|
||||
}
|
||||
EndpointMessageReactions = func(cID, mID, eID string) string {
|
||||
return EndpointChannelMessage(cID, mID) + "/reactions/" + eID
|
||||
}
|
||||
EndpointMessageReaction = func(cID, mID, eID, uID string) string {
|
||||
return EndpointMessageReactions(cID, mID, eID) + "/" + uID
|
||||
}
|
||||
|
||||
EndpointRelationships = func() string { return EndpointUsers + "@me" + "/relationships" }
|
||||
EndpointRelationship = func(uID string) string { return EndpointRelationships() + "/" + uID }
|
||||
EndpointRelationshipsMutual = func(uID string) string { return EndpointUsers + uID + "/relationships" }
|
||||
|
||||
EndpointGuildCreate = EndpointAPI + "guilds"
|
||||
|
||||
EndpointInvite = func(iID string) string { return EndpointAPI + "invite/" + iID }
|
||||
|
||||
EndpointIntegrationsJoin = func(iID string) string { return EndpointAPI + "integrations/" + iID + "/join" }
|
||||
|
||||
EndpointEmoji = func(eID string) string { return EndpointCDN + "emojis/" + eID + ".png" }
|
||||
EndpointEmojiAnimated = func(eID string) string { return EndpointCDN + "emojis/" + eID + ".gif" }
|
||||
|
||||
EndpointOauth2 = EndpointAPI + "oauth2/"
|
||||
EndpointApplications = EndpointOauth2 + "applications"
|
||||
EndpointApplication = func(aID string) string { return EndpointApplications + "/" + aID }
|
||||
EndpointApplicationsBot = func(aID string) string { return EndpointApplications + "/" + aID + "/bot" }
|
||||
EndpointApplicationAssets = func(aID string) string { return EndpointApplications + "/" + aID + "/assets" }
|
||||
)
|
||||
54
vendor/github.com/matterbridge/discordgo/interactions.go
generated
vendored
54
vendor/github.com/matterbridge/discordgo/interactions.go
generated
vendored
@@ -1,54 +0,0 @@
|
||||
package discordgo
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/ed25519"
|
||||
"encoding/hex"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// VerifyInteraction implements message verification of the discord interactions api
|
||||
// signing algorithm, as documented here:
|
||||
// https://discord.com/developers/docs/interactions/slash-commands#security-and-authorization
|
||||
func VerifyInteraction(r *http.Request, key ed25519.PublicKey) bool {
|
||||
var msg bytes.Buffer
|
||||
|
||||
signature := r.Header.Get("X-Signature-Ed25519")
|
||||
if signature == "" {
|
||||
return false
|
||||
}
|
||||
|
||||
sig, err := hex.DecodeString(signature)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
if len(sig) != ed25519.SignatureSize {
|
||||
return false
|
||||
}
|
||||
|
||||
timestamp := r.Header.Get("X-Signature-Timestamp")
|
||||
if timestamp == "" {
|
||||
return false
|
||||
}
|
||||
|
||||
msg.WriteString(timestamp)
|
||||
|
||||
defer r.Body.Close()
|
||||
var body bytes.Buffer
|
||||
|
||||
// at the end of the function, copy the original body back into the request
|
||||
defer func() {
|
||||
r.Body = ioutil.NopCloser(&body)
|
||||
}()
|
||||
|
||||
// copy body into buffers
|
||||
_, err = io.Copy(&msg, io.TeeReader(r.Body, &body))
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return ed25519.Verify(key, msg.Bytes(), sig)
|
||||
}
|
||||
1339
vendor/github.com/matterbridge/discordgo/structs.go
generated
vendored
1339
vendor/github.com/matterbridge/discordgo/structs.go
generated
vendored
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user