Skip to content

Commit

Permalink
Merge branch 'master' into threads
Browse files Browse the repository at this point in the history
  • Loading branch information
FedorLap2006 committed Feb 17, 2022
2 parents b1bb26d + d5bacb5 commit 4389357
Show file tree
Hide file tree
Showing 15 changed files with 895 additions and 671 deletions.
60 changes: 60 additions & 0 deletions .github/workflows/ci.yml
@@ -0,0 +1,60 @@
on:
push:
pull_request:

name: CI

jobs:
format:
runs-on: ubuntu-latest
steps:
- name: Install Go
uses: actions/setup-go@v2
with:
go-version: 1.17
- name: Code
uses: actions/checkout@v2
- name: Check diff between gofmt and code
run: diff <(gofmt -d .) <(echo -n)

test:
runs-on: ubuntu-latest
strategy:
matrix:
go-version: [1.13, 1.14, 1.15, 1.16, 1.17]
steps:
- name: Install Go
uses: actions/setup-go@v2
with:
go-version: ${{ matrix.go-version }}
- name: Code
uses: actions/checkout@v2
- run: go test -v -race ./...

lint:
runs-on: ubuntu-latest
steps:
- name: Install Go
uses: actions/setup-go@v2
with:
go-version: 1.17
- name: Code
uses: actions/checkout@v2
- name: Go vet
run: go vet -x ./...

- name: GolangCI-Lint
uses: golangci/golangci-lint-action@v2.5.2
if: github.event.name == 'pull_request'
with:
only-new-issues: true
skip-pkg-cache: true
skip-build-cache: true

- name: GolangCI-Lint
if: github.event.name != 'pull_request' # See https://github.com/golangci/golangci-lint-action/issues/362
run: |
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.43.0
$(go env GOPATH)/bin/golangci-lint run
19 changes: 19 additions & 0 deletions .golangci.yml
@@ -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
43 changes: 43 additions & 0 deletions components.go
Expand Up @@ -13,6 +13,7 @@ const (
ActionsRowComponent ComponentType = 1
ButtonComponent ComponentType = 2
SelectMenuComponent ComponentType = 3
TextInputComponent ComponentType = 4
)

// MessageComponent is a base interface for all message components.
Expand Down Expand Up @@ -42,12 +43,15 @@ func (umc *unmarshalableMessageComponent) UnmarshalJSON(src []byte) error {
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)
Expand Down Expand Up @@ -195,3 +199,42 @@ func (m SelectMenu) MarshalJSON() ([]byte, error) {
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
)
119 changes: 9 additions & 110 deletions discord.go
Expand Up @@ -14,8 +14,6 @@
package discordgo

import (
"errors"
"fmt"
"net/http"
"runtime"
"time"
Expand All @@ -24,32 +22,12 @@ import (
// 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) {
// 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{
Expand All @@ -74,88 +52,9 @@ func New(args ...interface{}) (s *Session, err error) {
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
}
}
s.Identify.Intents = IntentsAllWithoutPrivileged
s.Identify.Token = token
s.Token = token

return
}
58 changes: 20 additions & 38 deletions discord_test.go
Expand Up @@ -15,63 +15,45 @@ var (
dg *Session // Stores a global discordgo user session
dgBot *Session // Stores a global discordgo bot session

envToken = os.Getenv("DGU_TOKEN") // Token to use when authenticating the user account
envBotToken = os.Getenv("DGB_TOKEN") // Token to use when authenticating the bot account
envGuild = os.Getenv("DG_GUILD") // Guild ID to use for tests
envChannel = os.Getenv("DG_CHANNEL") // Channel ID to use for tests
envAdmin = os.Getenv("DG_ADMIN") // User ID of admin user to use for tests
envOAuth2Token = os.Getenv("DG_OAUTH2_TOKEN") // Token to use when authenticating using OAuth2 token
envBotToken = os.Getenv("DGB_TOKEN") // Token to use when authenticating the bot account
envGuild = os.Getenv("DG_GUILD") // Guild ID to use for tests
envChannel = os.Getenv("DG_CHANNEL") // Channel ID to use for tests
envAdmin = os.Getenv("DG_ADMIN") // User ID of admin user to use for tests
)

func init() {
func TestMain(m *testing.M) {
fmt.Println("Init is being called.")
if envBotToken != "" {
if d, err := New(envBotToken); err == nil {
dgBot = d
}
}

if d, err := New(envToken); err == nil {
dg = d
} else {
fmt.Println("dg is nil, error", err)
if envOAuth2Token == "" {
envOAuth2Token = os.Getenv("DGU_TOKEN")
}
}

//////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////// START OF TESTS

// TestNew tests the New() function without any arguments. This should return
// a valid Session{} struct and no errors.
func TestNew(t *testing.T) {

_, err := New()
if err != nil {
t.Errorf("New() returned error: %+v", err)
}
}

// TestInvalidToken tests the New() function with an invalid token
func TestInvalidToken(t *testing.T) {
d, err := New("asjkldhflkjasdh")
if err != nil {
t.Fatalf("New(InvalidToken) returned error: %+v", err)
if envOAuth2Token != "" {
if d, err := New(envOAuth2Token); err == nil {
dg = d
}
}

// New with just a token does not do any communication, so attempt an api call.
_, err = d.UserSettings()
if err == nil {
t.Errorf("New(InvalidToken), d.UserSettings returned nil error.")
}
os.Exit(m.Run())
}

//////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////// START OF TESTS

// TestNewToken tests the New() function with a Token.
func TestNewToken(t *testing.T) {

if envToken == "" {
if envOAuth2Token == "" {
t.Skip("Skipping New(token), DGU_TOKEN not set")
}

d, err := New(envToken)
d, err := New(envOAuth2Token)
if err != nil {
t.Fatalf("New(envToken) returned error: %+v", err)
}
Expand All @@ -86,11 +68,11 @@ func TestNewToken(t *testing.T) {
}

func TestOpenClose(t *testing.T) {
if envToken == "" {
if envOAuth2Token == "" {
t.Skip("Skipping TestClose, DGU_TOKEN not set")
}

d, err := New(envToken)
d, err := New(envOAuth2Token)
if err != nil {
t.Fatalf("TestClose, New(envToken) returned error: %+v", err)
}
Expand Down

0 comments on commit 4389357

Please sign in to comment.