diff --git a/.gitignore b/.gitignore index c3bc459..2f35a1c 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,7 @@ terraform.tfstate terraform.tfstate.backup .terraform/ + +.idea/ + +.env \ No newline at end of file diff --git a/discord/config.go b/discord/config.go index b973573..e27e856 100644 --- a/discord/config.go +++ b/discord/config.go @@ -1,12 +1,7 @@ package discord import ( - "fmt" - "net/http" - "strconv" - "time" - - "github.com/andersfylling/disgord" + "github.com/bwmarrin/discordgo" ) type Config struct { @@ -16,43 +11,16 @@ type Config struct { } type Context struct { - Client *disgord.Client - Config *Config -} - -// This type implements the http.RoundTripper interface -type LimitedRoundTripper struct { - Proxied http.RoundTripper + Session *discordgo.Session + Config *Config } -func (lrt LimitedRoundTripper) RoundTrip(req *http.Request) (res *http.Response, e error) { - // Do "before sending requests" actions here. - fmt.Printf("Sending request to %v\n", req.URL) - - // Send the request, get the response (or the error) - res, e = lrt.Proxied.RoundTrip(req) - - if res != nil && res.StatusCode == 429 { - retryAfter := res.Header.Get("X-RateLimit-Reset-After") - if retryAfter == "" { - retryAfter = res.Header.Get("Retry-After") - } - - dur, _ := strconv.Atoi(retryAfter) - time.Sleep(time.Duration(dur) * time.Millisecond) - - return lrt.RoundTrip(req) +func (c *Config) Client(version string) (*Context, error) { + session, err := discordgo.New(c.Token) + session.UserAgent = "discord-terraform/" + version + if err != nil { + return nil, err } - return -} - -func (c *Config) Client() (*Context, error) { - httpClient := &http.Client{Transport: LimitedRoundTripper{http.DefaultTransport}} - client := disgord.New(disgord.Config{ - BotToken: c.Token, - HTTPClient: httpClient, - }) - - return &Context{Client: client, Config: c}, nil + return &Context{Config: c, Session: session}, nil } diff --git a/discord/data_source_discord_color_test.go b/discord/data_source_discord_color_test.go new file mode 100644 index 0000000..a37d04b --- /dev/null +++ b/discord/data_source_discord_color_test.go @@ -0,0 +1,42 @@ +package discord + +import ( + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "testing" +) + +func TestAccDatasourceDiscordColor(t *testing.T) { + name := "data.discord_color.example" + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProviderFactories: providerFactories, + Steps: []resource.TestStep{ + { + Config: testAccDatasourceDiscordColorRGB, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + name, "dec", "203569"), + ), + }, + { + Config: testAccDatasourceDiscordColorHex, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + name, "dec", "203569"), + ), + }, + }, + }) +} + +const testAccDatasourceDiscordColorHex = ` +data "discord_color" "example" { + hex = "#031b31" +} +` + +const testAccDatasourceDiscordColorRGB = ` +data "discord_color" "example" { + rgb = "rgb(3, 27, 49)" +} +` diff --git a/discord/data_source_discord_local_image_test.go b/discord/data_source_discord_local_image_test.go new file mode 100644 index 0000000..10e31ad --- /dev/null +++ b/discord/data_source_discord_local_image_test.go @@ -0,0 +1,29 @@ +package discord + +import ( + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "testing" +) + +func TestAccDatasourceDiscordLocalImage(t *testing.T) { + name := "data.discord_local_image.example" + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProviderFactories: providerFactories, + Steps: []resource.TestStep{ + { + Config: testAccDatasourceDiscordLocalImage, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(name, "file", "provider.go"), + resource.TestCheckResourceAttrSet(name, "data_uri"), + ), + }, + }, + }) +} + +const testAccDatasourceDiscordLocalImage = ` +data "discord_local_image" "example" { + file = "provider.go" +} +` diff --git a/discord/data_source_discord_member.go b/discord/data_source_discord_member.go index 6067697..811abc4 100644 --- a/discord/data_source_discord_member.go +++ b/discord/data_source_discord_member.go @@ -2,8 +2,8 @@ package discord import ( "fmt" + "github.com/bwmarrin/discordgo" - "github.com/andersfylling/disgord" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "golang.org/x/net/context" @@ -25,14 +25,13 @@ func dataSourceDiscordMember() *schema.Resource { }, "username": { ExactlyOneOf: []string{"user_id", "username"}, - RequiredWith: []string{"username", "discriminator"}, Type: schema.TypeString, Optional: true, }, "discriminator": { - RequiredWith: []string{"username", "discriminator"}, - Type: schema.TypeString, - Optional: true, + Type: schema.TypeString, + Optional: true, + Deprecated: "Discriminator is being deprecated by Discord. Only use this if there are users who haven't migrated their username.", }, "joined_at": { Type: schema.TypeString, @@ -66,34 +65,36 @@ func dataSourceDiscordMember() *schema.Resource { func dataSourceMemberRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { var diags diag.Diagnostics - var member *disgord.Member + var member *discordgo.Member var memberErr error - client := m.(*Context).Client - serverId := getId(d.Get("server_id").(string)) + client := m.(*Context).Session + serverId := d.Get("server_id").(string) if v, ok := d.GetOk("user_id"); ok { - member, memberErr = client.Guild(serverId).Member(getId(v.(string))).Get() + + member, memberErr = client.GuildMember(serverId, v.(string), discordgo.WithContext(ctx)) } if v, ok := d.GetOk("username"); ok { username := v.(string) - discriminator := d.Get("discriminator").(string) - - members, err := client.Guild(serverId).GetMembers(&disgord.GetMembers{Limit: 0}) + members, err := client.GuildMembersSearch(serverId, username, 1, discordgo.WithContext(ctx)) if err != nil { - return diag.Errorf("Failed to fetch members for %s: %s", serverId.String(), err.Error()) + return diag.Errorf("Failed to fetch members for %s: %s", serverId, err.Error()) } + discriminator := d.Get("discriminator").(string) memberErr = fmt.Errorf("failed to find member by name#discriminator: %s#%s", username, discriminator) for _, m := range members { - if m.User.Username == username && m.User.Discriminator.String() == discriminator { + if m.User.Username == username && m.User.Discriminator == discriminator { member = m memberErr = nil break } } } - + if memberErr != nil { + return diag.FromErr(memberErr) + } d.Set("in_server", memberErr == nil) if memberErr != nil { d.Set("joined_at", nil) @@ -108,12 +109,14 @@ func dataSourceMemberRead(ctx context.Context, d *schema.ResourceData, m interfa roles := make([]string, 0, len(member.Roles)) for _, r := range member.Roles { - roles = append(roles, r.String()) + roles = append(roles, r) + } + if member.PremiumSince == nil { + d.Set("premium_since", nil) } - d.SetId(member.User.ID.String()) + d.SetId(member.User.ID) d.Set("joined_at", member.JoinedAt.String()) - d.Set("premium_since", member.PremiumSince.String()) d.Set("roles", roles) d.Set("username", member.User.Username) d.Set("discriminator", member.User.Discriminator) diff --git a/discord/data_source_discord_member_test.go b/discord/data_source_discord_member_test.go new file mode 100644 index 0000000..d56fbab --- /dev/null +++ b/discord/data_source_discord_member_test.go @@ -0,0 +1,64 @@ +package discord + +import ( + "fmt" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "os" + "testing" +) + +func TestAccDatasourceDiscordMember(t *testing.T) { + testServerID := os.Getenv("DISCORD_TEST_SERVER_ID") + testUserID := os.Getenv("DISCORD_TEST_USER_ID") + testUsername := os.Getenv("DISCORD_TEST_USERNAME") + if testServerID == "" || testUserID == "" || testUsername == "" { + t.Skip("DISCORD_TEST_SERVER_ID, DISCORD_TEST_USER_ID, and DISCORD_TEST_USERNAME envvars must be set for acceptance tests") + } + + name := "data.discord_member.example" + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProviderFactories: providerFactories, + Steps: []resource.TestStep{ + { + Config: testAccDatasourceDiscordMemberUserID(testServerID, testUserID), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(name, "server_id", testServerID), + resource.TestCheckResourceAttr(name, "user_id", testUserID), + resource.TestCheckResourceAttrSet(name, "joined_at"), + resource.TestCheckResourceAttrSet(name, "avatar"), + resource.TestCheckResourceAttrSet(name, "roles.#"), + resource.TestCheckResourceAttr(name, "in_server", "true"), + ), + }, + { + Config: testAccDatasourceDiscordMemberUsername(testServerID, testUsername), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(name, "server_id", testServerID), + resource.TestCheckResourceAttr(name, "username", testUsername), + resource.TestCheckResourceAttrSet(name, "joined_at"), + resource.TestCheckResourceAttrSet(name, "avatar"), + resource.TestCheckResourceAttrSet(name, "roles.#"), + resource.TestCheckResourceAttr(name, "in_server", "true"), + ), + }, + }, + }) +} + +func testAccDatasourceDiscordMemberUserID(serverId string, userID string) string { + return fmt.Sprintf(` + data "discord_member" "example" { + server_id = "%[1]s" + user_id = "%[2]s" + }`, serverId, userID) +} + +func testAccDatasourceDiscordMemberUsername(serverId string, username string) string { + return fmt.Sprintf(` + data "discord_member" "example" { + server_id = "%[1]s" + username = "%[2]s" + discriminator = "0" + }`, serverId, username) +} diff --git a/discord/data_source_discord_permission.go b/discord/data_source_discord_permission.go index 2437360..bd41df9 100644 --- a/discord/data_source_discord_permission.go +++ b/discord/data_source_discord_permission.go @@ -3,9 +3,9 @@ package discord import ( "context" "fmt" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "strconv" - "github.com/hashicorp/go-cty/cty" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) @@ -83,19 +83,10 @@ func dataSourceDiscordPermission() *schema.Resource { } for k := range permissions { schemaMap[k] = &schema.Schema{ - Optional: true, - Type: schema.TypeString, - Default: "unset", - ValidateDiagFunc: func(v interface{}, path cty.Path) (diags diag.Diagnostics) { - str := v.(string) - allowed := []string{"allow", "unset", "deny"} - - if contains(allowed, str) { - return diags - } else { - return append(diags, diag.Errorf("%s is not an allowed value. Pick one of: allowed, unset, deny", str)...) - } - }, + Optional: true, + Type: schema.TypeString, + Default: "unset", + ValidateFunc: validation.StringInSlice([]string{"allow", "unset", "deny"}, false), } } diff --git a/discord/data_source_discord_permission_test.go b/discord/data_source_discord_permission_test.go new file mode 100644 index 0000000..e03ce8c --- /dev/null +++ b/discord/data_source_discord_permission_test.go @@ -0,0 +1,49 @@ +package discord + +import ( + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "testing" +) + +func TestAccDatasourceDiscordPermission(t *testing.T) { + name := "data.discord_permission.example" + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProviderFactories: providerFactories, + Steps: []resource.TestStep{ + { + Config: testAccDatasourceDiscordPermissionSimple, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(name, "administrator", "allow"), + resource.TestCheckResourceAttr(name, "allow_bits", "8"), + ), + }, + { + Config: testAccDatasourceDiscordPermissionComplex, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(name, "send_messages", "allow"), + resource.TestCheckResourceAttr(name, "embed_links", "allow"), + resource.TestCheckResourceAttr(name, "allow_bits", "18432"), + resource.TestCheckResourceAttr(name, "speak", "deny"), + resource.TestCheckResourceAttr(name, "change_nickname", "deny"), + resource.TestCheckResourceAttr(name, "deny_bits", "69206016"), + ), + }, + }, + }) +} + +const testAccDatasourceDiscordPermissionSimple = ` +data "discord_permission" "example" { + administrator = "allow" +} +` + +const testAccDatasourceDiscordPermissionComplex = ` +data "discord_permission" "example" { + send_messages = "allow" + embed_links = "allow" + speak = "deny" + change_nickname = "deny" +} +` diff --git a/discord/data_source_discord_role.go b/discord/data_source_discord_role.go index 2b4ee44..459ee58 100644 --- a/discord/data_source_discord_role.go +++ b/discord/data_source_discord_role.go @@ -2,8 +2,8 @@ package discord import ( "context" + "github.com/bwmarrin/discordgo" - "github.com/andersfylling/disgord" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) @@ -27,7 +27,7 @@ func dataSourceDiscordRole() *schema.Resource { Optional: true, }, "position": { - Type: schema.TypeString, + Type: schema.TypeInt, Computed: true, }, "color": { @@ -57,43 +57,35 @@ func dataSourceDiscordRole() *schema.Resource { func dataSourceDiscordRoleRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { var diags diag.Diagnostics var err error - var role *disgord.Role - client := m.(*Context).Client + var role *discordgo.Role + client := m.(*Context).Session - serverId := getId(d.Get("server_id").(string)) - server, err := client.Guild(serverId).Get() + serverId := d.Get("server_id").(string) + server, err := client.Guild(serverId, discordgo.WithContext(ctx)) if err != nil { - return diag.Errorf("Failed to fetch server %s: %s", serverId.String(), err.Error()) + return diag.Errorf("Failed to fetch server %s: %s", serverId, err.Error()) } - if v, ok := d.GetOk("role_id"); ok { - role, err = server.Role(getId(v.(string))) - if err != nil { - return diag.Errorf("Failed to fetch role %s: %s", v.(string), err.Error()) + roleID := d.Get("role_id").(string) + roleName := d.Get("name").(string) + for _, r := range server.Roles { + if r.ID == roleID || r.Name == roleName { + role = r + break } } - - if v, ok := d.GetOk("name"); ok { - roles, err := server.RoleByName(v.(string)) - if err != nil { - return diag.Errorf("Failed to fetch role %s: %s", v.(string), err.Error()) - } - - if len(roles) <= 0 { - return diag.Errorf("Failed to fetch role %s", v.(string)) - } - - role = roles[0] + if role == nil { + return diag.Errorf("Failed to find role by ID %s or name: %s", roleID, roleName) } - d.SetId(role.ID.String()) - d.Set("role_id", role.ID.String()) + d.SetId(role.ID) + d.Set("role_id", role.ID) d.Set("name", role.Name) - d.Set("position", len(server.Roles)-role.Position) + d.Set("position", role.Position) d.Set("color", role.Color) d.Set("hoist", role.Hoist) d.Set("mentionable", role.Mentionable) - d.Set("permissions", role.Permissions) + d.Set("permissions", int(role.Permissions)) d.Set("managed", role.Managed) return diags diff --git a/discord/data_source_discord_role_test.go b/discord/data_source_discord_role_test.go new file mode 100644 index 0000000..0682ad9 --- /dev/null +++ b/discord/data_source_discord_role_test.go @@ -0,0 +1,67 @@ +package discord + +import ( + "fmt" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "os" + "testing" +) + +func TestAccDatasourceDiscordRole(t *testing.T) { + testServerID := os.Getenv("DISCORD_TEST_SERVER_ID") + testRoleID := os.Getenv("DISCORD_TEST_ROLE_ID") + testRoleName := os.Getenv("DISCORD_TEST_ROLE_NAME") + if testServerID == "" || testRoleID == "" || testRoleName == "" { + t.Skip("DISCORD_TEST_SERVER_ID, DISCORD_TEST_ROLE_ID, and DISCORD_TEST_ROLE_NAME envvars must be set for acceptance tests") + } + + name := "data.discord_role.example" + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProviderFactories: providerFactories, + Steps: []resource.TestStep{ + { + Config: testAccDatasourceDiscordRoleID(testServerID, testRoleID), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(name, "server_id", testServerID), + resource.TestCheckResourceAttr(name, "role_id", testRoleID), + resource.TestCheckResourceAttr(name, "position", "1"), + resource.TestCheckResourceAttrSet(name, "permissions"), + resource.TestCheckResourceAttrSet(name, "color"), + resource.TestCheckResourceAttr(name, "hoist", "false"), + resource.TestCheckResourceAttr(name, "mentionable", "false"), + resource.TestCheckResourceAttr(name, "managed", "false"), + ), + }, + { + Config: testAccDatasourceDiscordRoleName(testServerID, testRoleName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(name, "server_id", testServerID), + resource.TestCheckResourceAttr(name, "name", testRoleName), + resource.TestCheckResourceAttr(name, "position", "1"), + resource.TestCheckResourceAttrSet(name, "permissions"), + resource.TestCheckResourceAttrSet(name, "color"), + resource.TestCheckResourceAttr(name, "hoist", "false"), + resource.TestCheckResourceAttr(name, "mentionable", "false"), + resource.TestCheckResourceAttr(name, "managed", "false"), + ), + }, + }, + }) +} + +func testAccDatasourceDiscordRoleID(serverId string, roleID string) string { + return fmt.Sprintf(` + data "discord_role" "example" { + server_id = "%[1]s" + role_id = "%[2]s" + }`, serverId, roleID) +} + +func testAccDatasourceDiscordRoleName(serverId string, roleName string) string { + return fmt.Sprintf(` + data "discord_role" "example" { + server_id = "%[1]s" + name = "%[2]s" + }`, serverId, roleName) +} diff --git a/discord/data_source_discord_server.go b/discord/data_source_discord_server.go index a36a1d7..638649b 100644 --- a/discord/data_source_discord_server.go +++ b/discord/data_source_discord_server.go @@ -2,8 +2,7 @@ package discord import ( "context" - - "github.com/andersfylling/disgord" + "github.com/bwmarrin/discordgo" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) @@ -55,7 +54,7 @@ func dataSourceDiscordServer() *schema.Resource { Computed: true, }, "owner_id": { - Type: schema.TypeInt, + Type: schema.TypeString, Computed: true, }, }, @@ -65,24 +64,27 @@ func dataSourceDiscordServer() *schema.Resource { func dataSourceDiscordServerRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { var diags diag.Diagnostics var err error - var server *disgord.Guild - client := m.(*Context).Client + var server *discordgo.Guild + client := m.(*Context).Session if v, ok := d.GetOk("server_id"); ok { - server, err = client.Guild(getId(v.(string))).Get() + server, err = client.Guild(v.(string), discordgo.WithContext(ctx)) if err != nil { return diag.Errorf("Failed to fetch server %s: %s", v.(string), err.Error()) } } if v, ok := d.GetOk("name"); ok { - guilds, err := client.CurrentUser().GetGuilds(&disgord.GetCurrentUserGuilds{Limit: 1000}) + guilds, err := client.UserGuilds(1000, "", "", false, discordgo.WithContext(ctx)) if err != nil { return diag.Errorf("Failed to fetch server %s: %s", v.(string), err.Error()) } for _, s := range guilds { if s.Name == v.(string) { - server = s + server, err = client.Guild(v.(string), discordgo.WithContext(ctx)) + if err != nil { + return diag.Errorf("Failed to fetch server %s: %s", v.(string), err.Error()) + } break } } @@ -92,8 +94,8 @@ func dataSourceDiscordServerRead(ctx context.Context, d *schema.ResourceData, m } } - d.SetId(server.ID.String()) - d.Set("server_id", server.ID.String()) + d.SetId(server.ID) + d.Set("server_id", server.ID) d.Set("name", server.Name) d.Set("region", server.Region) d.Set("afk_timeout", server.AfkTimeout) @@ -103,11 +105,11 @@ func dataSourceDiscordServerRead(ctx context.Context, d *schema.ResourceData, m d.Set("verification_level", int(server.VerificationLevel)) d.Set("explicit_content_filter", int(server.ExplicitContentFilter)) - if !server.AfkChannelID.IsZero() { - d.Set("afk_channel_id", server.AfkChannelID.String()) + if server.AfkChannelID != "" { + d.Set("afk_channel_id", server.AfkChannelID) } - if !server.OwnerID.IsZero() { - d.Set("owner_id", server.OwnerID.String()) + if server.OwnerID != "" { + d.Set("owner_id", server.OwnerID) } return diags diff --git a/discord/data_source_discord_server_test.go b/discord/data_source_discord_server_test.go new file mode 100644 index 0000000..5aa6a3b --- /dev/null +++ b/discord/data_source_discord_server_test.go @@ -0,0 +1,42 @@ +package discord + +import ( + "fmt" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "os" + "testing" +) + +func TestAccDatasourceDiscordServer(t *testing.T) { + testServerID := os.Getenv("DISCORD_TEST_SERVER_ID") + if testServerID == "" { + t.Skip("DISCORD_TEST_SERVER_ID is not set") + } + + name := "data.discord_server.example" + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProviderFactories: providerFactories, + Steps: []resource.TestStep{ + { + Config: testAccDatasourceDiscordServer(testServerID), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(name, "name", "Discord Terraform Test Server"), + resource.TestCheckResourceAttrSet(name, "region"), + resource.TestCheckResourceAttr(name, "default_message_notifications", "1"), + resource.TestCheckResourceAttr(name, "verification_level", "1"), + resource.TestCheckResourceAttr(name, "explicit_content_filter", "2"), + resource.TestCheckResourceAttr(name, "afk_timeout", "300"), + resource.TestCheckResourceAttrSet(name, "owner_id"), + ), + }, + }, + }) +} + +func testAccDatasourceDiscordServer(serverId string) string { + return fmt.Sprintf(` + data "discord_server" "example" { + server_id = "%[1]s" + }`, serverId) +} diff --git a/discord/data_source_discord_system_channel.go.go b/discord/data_source_discord_system_channel.go similarity index 74% rename from discord/data_source_discord_system_channel.go.go rename to discord/data_source_discord_system_channel.go index 181f9d8..605cba9 100644 --- a/discord/data_source_discord_system_channel.go.go +++ b/discord/data_source_discord_system_channel.go @@ -2,8 +2,8 @@ package discord import ( "context" + "github.com/bwmarrin/discordgo" - "github.com/andersfylling/disgord" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) @@ -17,7 +17,7 @@ func dataSourceDiscordSystemChannel() *schema.Resource { Required: true, }, "system_channel_id": { - Type: schema.TypeInt, + Type: schema.TypeString, Computed: true, }, }, @@ -27,13 +27,14 @@ func dataSourceDiscordSystemChannel() *schema.Resource { func dataSourceDiscordSystemChannelRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { var diags diag.Diagnostics var err error - var server *disgord.Guild - client := m.(*Context).Client + var server *discordgo.Guild + client := m.(*Context).Session - serverId := d.Id() - if server, err = client.Guild(getId(serverId)).Get(); err != nil { + serverId := d.Get("server_id").(string) + if server, err = client.Guild(serverId, discordgo.WithContext(ctx)); err != nil { return diag.Errorf("Failed to fetch server %s: %s", serverId, err.Error()) } else { + d.SetId(serverId) d.Set("system_channel_id", server.SystemChannelID) return diags diff --git a/discord/data_source_discord_system_channel_test.go b/discord/data_source_discord_system_channel_test.go new file mode 100644 index 0000000..c3ae47c --- /dev/null +++ b/discord/data_source_discord_system_channel_test.go @@ -0,0 +1,37 @@ +package discord + +import ( + "fmt" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "os" + "testing" +) + +func TestAccDatasourceDiscordSystemChannel(t *testing.T) { + testServerID := os.Getenv("DISCORD_TEST_SERVER_ID") + if testServerID == "" { + t.Skip("DISCORD_TEST_SERVER_ID envvar must be set for acceptance tests") + } + + name := "data.discord_system_channel.example" + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProviderFactories: providerFactories, + Steps: []resource.TestStep{ + { + Config: testAccDatasourceDiscordSystemChannel(testServerID), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(name, "server_id", testServerID), + resource.TestCheckResourceAttrSet(name, "system_channel_id"), + ), + }, + }, + }) +} + +func testAccDatasourceDiscordSystemChannel(serverId string) string { + return fmt.Sprintf(` + data "discord_system_channel" "example" { + server_id = "%[1]s" + }`, serverId) +} diff --git a/discord/provider.go b/discord/provider.go index 04644ed..fd53ecc 100644 --- a/discord/provider.go +++ b/discord/provider.go @@ -2,70 +2,93 @@ package discord import ( "context" + "os" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) -func Provider() *schema.Provider { - return &schema.Provider{ - Schema: map[string]*schema.Schema{ - "token": { - Type: schema.TypeString, - Required: true, +func Provider(version string) func() *schema.Provider { + return func() *schema.Provider { + p := &schema.Provider{ + Schema: map[string]*schema.Schema{ + "token": { + Type: schema.TypeString, + Optional: true, + Description: "Discord API Token. This can be found in the Discord Developer Portal. This includes the `Bot` prefix. Can also be set via the `DISCORD_TOKEN` environment variable.", + }, + "client_id": { + Type: schema.TypeString, + Optional: true, + }, + "secret": { + Type: schema.TypeString, + Optional: true, + }, }, - "client_id": { - Type: schema.TypeString, - Optional: true, - }, - "secret": { - Type: schema.TypeString, - Optional: true, - }, - }, - ResourcesMap: map[string]*schema.Resource{ - "discord_server": resourceDiscordServer(), - "discord_managed_server": resourceDiscordManagedServer(), - "discord_category_channel": resourceDiscordCategoryChannel(), - "discord_text_channel": resourceDiscordTextChannel(), - "discord_voice_channel": resourceDiscordVoiceChannel(), - "discord_news_channel": resourceDiscordNewsChannel(), - "discord_channel_permission": resourceDiscordChannelPermission(), - "discord_invite": resourceDiscordInvite(), - "discord_role": resourceDiscordRole(), - "discord_role_everyone": resourceDiscordRoleEveryone(), - "discord_member_roles": resourceDiscordMemberRoles(), - "discord_message": resourceDiscordMessage(), - "discord_system_channel": resourceDiscordSystemChannel(), - "discord_webhook": resourceDiscordWebhook(), - }, + ResourcesMap: map[string]*schema.Resource{ + "discord_server": resourceDiscordServer(), + "discord_managed_server": resourceDiscordManagedServer(), + "discord_category_channel": resourceDiscordCategoryChannel(), + "discord_text_channel": resourceDiscordTextChannel(), + "discord_voice_channel": resourceDiscordVoiceChannel(), + "discord_news_channel": resourceDiscordNewsChannel(), + "discord_channel_permission": resourceDiscordChannelPermission(), + "discord_invite": resourceDiscordInvite(), + "discord_role": resourceDiscordRole(), + "discord_role_everyone": resourceDiscordRoleEveryone(), + "discord_member_roles": resourceDiscordMemberRoles(), + "discord_message": resourceDiscordMessage(), + "discord_system_channel": resourceDiscordSystemChannel(), + "discord_webhook": resourceDiscordWebhook(), + }, - DataSourcesMap: map[string]*schema.Resource{ - "discord_permission": dataSourceDiscordPermission(), - "discord_color": dataSourceDiscordColor(), - "discord_local_image": dataSourceDiscordLocalImage(), - "discord_role": dataSourceDiscordRole(), - "discord_server": dataSourceDiscordServer(), - "discord_member": dataSourceDiscordMember(), - "discord_system_channel": dataSourceDiscordSystemChannel(), - }, + DataSourcesMap: map[string]*schema.Resource{ + "discord_permission": dataSourceDiscordPermission(), + "discord_color": dataSourceDiscordColor(), + "discord_local_image": dataSourceDiscordLocalImage(), + "discord_role": dataSourceDiscordRole(), + "discord_server": dataSourceDiscordServer(), + "discord_member": dataSourceDiscordMember(), + "discord_system_channel": dataSourceDiscordSystemChannel(), + }, - ConfigureContextFunc: providerConfigure, + ConfigureContextFunc: providerConfigure(version), + } + return p } } -func providerConfigure(_ context.Context, d *schema.ResourceData) (interface{}, diag.Diagnostics) { - var diags diag.Diagnostics +func providerConfigure(version string) func(ctx context.Context, d *schema.ResourceData) (interface{}, diag.Diagnostics) { + return func(ctx context.Context, d *schema.ResourceData) (interface{}, diag.Diagnostics) { + var diags diag.Diagnostics - config := Config{ - Token: d.Get("token").(string), - } + var token string + if v, ok := d.GetOk("token"); ok { + token = v.(string) + } else { + token = os.Getenv("DISCORD_TOKEN") + } + if token == "" { + diags = append(diags, diag.Diagnostic{ + Severity: diag.Error, + Summary: "Missing required token", + Detail: "The `token` argument or `DISCORD_TOKEN` environment variable must be set", + }) + return nil, diags + } + config := Config{ + Token: token, + ClientID: d.Get("client_id").(string), + Secret: d.Get("secret").(string), + } - client, err := config.Client() - if err != nil { - return nil, diag.FromErr(err) - } + client, err := config.Client(version) + if err != nil { + return nil, diag.FromErr(err) + } - return client, diags + return client, diags + } } diff --git a/discord/provider_test.go b/discord/provider_test.go new file mode 100644 index 0000000..8bbe831 --- /dev/null +++ b/discord/provider_test.go @@ -0,0 +1,31 @@ +package discord + +import ( + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "os" + "testing" +) + +// providerFactories are used to instantiate a provider during acceptance testing. +// The factory function will be invoked for every Terraform CLI command executed +// to create a provider server to which the CLI can reattach. +var providerFactories = map[string]func() (*schema.Provider, error){ + "discord": func() (*schema.Provider, error) { + return Provider("dev")(), nil + }, +} + +func TestProvider(t *testing.T) { + if err := Provider("dev")().InternalValidate(); err != nil { + t.Fatalf("err: %s", err) + } +} + +func testAccPreCheck(t *testing.T) { + // You can add code here to run prior to any test case execution, for example assertions + // about the appropriate environment variables being set are common to see in a pre-check + // function. + if os.Getenv("DISCORD_TOKEN") == "" { + t.Fatal("DISCORD_TOKEN must be set for acceptance tests") + } +} diff --git a/discord/resource_discord_catergory_channel_test.go b/discord/resource_discord_catergory_channel_test.go new file mode 100644 index 0000000..fb74340 --- /dev/null +++ b/discord/resource_discord_catergory_channel_test.go @@ -0,0 +1,41 @@ +package discord + +import ( + "fmt" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "os" + "testing" +) + +func TestAccResourceDiscordCategoryChannel(t *testing.T) { + testServerID := os.Getenv("DISCORD_TEST_SERVER_ID") + if testServerID == "" { + t.Skip("DISCORD_TEST_SERVER_ID envvar must be set for acceptance tests") + } + name := "discord_category_channel.example" + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProviderFactories: providerFactories, + Steps: []resource.TestStep{ + { + Config: testAccResourceDiscordSystemChannel(testServerID), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(name, "server_id", testServerID), + resource.TestCheckResourceAttr(name, "name", "terraform-system-channel"), + resource.TestCheckResourceAttr(name, "type", "category"), + resource.TestCheckResourceAttr(name, "position", "1"), + resource.TestCheckResourceAttrSet(name, "channel_id"), + ), + }, + }, + }) +} + +func testAccResourceDiscordSystemChannel(serverID string) string { + return fmt.Sprintf(` + resource "discord_category_channel" "example" { + server_id = "%[1]s" + name = "terraform-system-channel" + position = 1 + }`, serverID) +} diff --git a/discord/resource_discord_channel.go b/discord/resource_discord_channel.go index 0e3d2e4..5c1eced 100644 --- a/discord/resource_discord_channel.go +++ b/discord/resource_discord_channel.go @@ -3,9 +3,9 @@ package discord import ( "errors" "fmt" + "github.com/bwmarrin/discordgo" "strings" - "github.com/andersfylling/disgord" "github.com/hashicorp/go-cty/cty" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" @@ -18,6 +18,14 @@ func getChannelSchema(channelType string, s map[string]*schema.Schema) map[strin Type: schema.TypeString, Required: true, }, + "channel_id": { + Type: schema.TypeString, + Computed: true, + }, + "category": { + Type: schema.TypeString, + Optional: true, + }, "type": { Type: schema.TypeString, Required: true, @@ -115,22 +123,25 @@ func validateChannel(d *schema.ResourceData) (bool, error) { func resourceChannelCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { var diags diag.Diagnostics - client := m.(*Context).Client + client := m.(*Context).Session if ok, reason := validateChannel(d); !ok { return diag.FromErr(reason) } - serverId := getMajorId(d.Get("server_id")) + serverId := d.Get("server_id").(string) channelType := d.Get("type").(string) - channelTypeInt, _ := getDiscordChannelType(channelType) + channelTypeInt, okay := getDiscordChannelType(channelType) + if !okay { + return diag.Errorf("Invalid channel type: %s", channelType) + } var ( topic string - bitrate uint = 64000 - userlimit uint + bitrate = 64000 + userlimit int nsfw bool - parentId disgord.Snowflake + parentId string ) switch channelType { @@ -146,10 +157,10 @@ func resourceChannelCreate(ctx context.Context, d *schema.ResourceData, m interf case "voice": { if v, ok := d.GetOk("bitrate"); ok { - bitrate = uint(v.(int)) + bitrate = v.(int) } if v, ok := d.GetOk("user_limit"); ok { - userlimit = uint(v.(int)) + userlimit = v.(int) } } } @@ -158,40 +169,39 @@ func resourceChannelCreate(ctx context.Context, d *schema.ResourceData, m interf if !isCategoryCh { if v, ok := d.GetOk("category"); ok { - parentId = getId(v.(string)) + parentId = v.(string) } } - - channel, err := client.Guild(serverId).CreateChannel(d.Get("name").(string), &disgord.CreateGuildChannel{ + channel, err := client.GuildChannelCreateComplex(serverId, discordgo.GuildChannelCreateData{ + Name: d.Get("name").(string), Type: channelTypeInt, Topic: topic, Bitrate: bitrate, UserLimit: userlimit, ParentID: parentId, NSFW: nsfw, - Position: d.Get("position").(int), - }) + }, discordgo.WithContext(ctx)) if err != nil { return diag.Errorf("Failed to create channel: %s", err.Error()) } - d.SetId(channel.ID.String()) + d.SetId(channel.ID) d.Set("server_id", serverId) - d.Set("channel_id", channel.ID.String()) + d.Set("channel_id", channel.ID) if !isCategoryCh { if v, ok := d.GetOk("sync_perms_with_category"); ok && v.(bool) { - if channel.ParentID.IsZero() { - return append(diags, diag.Errorf("Can't sync permissions with category. Channel (%s) doesn't have a category", channel.ID.String())...) + if channel.ParentID == "" { + return append(diags, diag.Errorf("Can't sync permissions with category. Channel (%s) doesn't have a category", channel.ID)...) } - parent, err := client.Channel(channel.ParentID).Get() + parent, err := client.Channel(channel.ParentID) if err != nil { - return append(diags, diag.Errorf("Can't sync permissions with category. Channel (%s) doesn't have a category", channel.ID.String())...) + return append(diags, diag.Errorf("Can't sync permissions with category. Channel (%s) doesn't have a category", channel.ID)...) } if err = syncChannelPermissions(client, ctx, parent, channel); err != nil { - return append(diags, diag.Errorf("Can't sync permissions with category: %s", channel.ID.String())...) + return append(diags, diag.Errorf("Can't sync permissions with category: %s", channel.ID)...) } } } @@ -201,9 +211,9 @@ func resourceChannelCreate(ctx context.Context, d *schema.ResourceData, m interf func resourceChannelRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { var diags diag.Diagnostics - client := m.(*Context).Client + client := m.(*Context).Session - channel, err := client.Channel(getId(d.Id())).Get() + channel, err := client.Channel(d.Id(), discordgo.WithContext(ctx)) if err != nil { return diag.Errorf("Failed to fetch channel %s: %s", d.Id(), err.Error()) } @@ -213,17 +223,19 @@ func resourceChannelRead(ctx context.Context, d *schema.ResourceData, m interfac return diag.Errorf("Invalid channel type: %d", channel.Type) } - d.Set("server_id", channel.GuildID.String()) + d.Set("server_id", channel.GuildID) d.Set("type", channelType) d.Set("name", channel.Name) d.Set("position", channel.Position) switch channelType { - case "text", "news": + case "text": { d.Set("topic", channel.Topic) d.Set("nsfw", channel.NSFW) } + case "news": + d.Set("topic", channel.Topic) case "voice": { d.Set("bitrate", channel.Bitrate) @@ -232,12 +244,12 @@ func resourceChannelRead(ctx context.Context, d *schema.ResourceData, m interfac } if channelType != "category" { - if channel.ParentID.IsZero() { + if channel.ParentID == "" { d.Set("sync_perms_with_category", false) } else { - parent, err := client.Channel(channel.ParentID).Get() + parent, err := client.Channel(channel.ParentID) if err != nil { - return diag.Errorf("Failed to fetch category of channel %s: %s", channel.ID.String(), err.Error()) + return diag.Errorf("Failed to fetch category of channel %s: %s", channel.ID, err.Error()) } synced := arePermissionsSynced(channel, parent) @@ -245,10 +257,10 @@ func resourceChannelRead(ctx context.Context, d *schema.ResourceData, m interfac } } - if channel.ParentID.IsZero() { + if channel.ParentID == "" { d.Set("category", nil) } else { - d.Set("category", channel.ParentID.String()) + d.Set("category", channel.ParentID) } return diags @@ -256,26 +268,26 @@ func resourceChannelRead(ctx context.Context, d *schema.ResourceData, m interfac func resourceChannelUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { var diags diag.Diagnostics - client := m.(*Context).Client + client := m.(*Context).Session if ok, reason := validateChannel(d); !ok { return diag.FromErr(reason) } - channel, _ := client.Channel(getId(d.Id())).Get() + channel, _ := client.Channel(d.Id(), discordgo.WithContext(ctx)) channelType := d.Get("type").(string) var ( name string - position uint + position int topic string nsfw bool - bitRate uint = 64000 - userLimit uint - parentId *disgord.Snowflake + bitRate = 64000 + userLimit int + parentId string ) name = map[bool]string{true: d.Get("name").(string), false: channel.Name}[d.HasChange("name")] - position = map[bool]uint{true: uint(d.Get("position").(int)), false: uint(channel.Position)}[d.HasChange("position")] + position = map[bool]int{true: int(d.Get("position").(int)), false: int(channel.Position)}[d.HasChange("position")] switch channelType { case "text", "news": @@ -285,41 +297,40 @@ func resourceChannelUpdate(ctx context.Context, d *schema.ResourceData, m interf } case "voice": { - bitRate = map[bool]uint{true: uint(d.Get("bitrate").(int)), false: channel.Bitrate}[d.HasChange("bitrate")] - userLimit = map[bool]uint{true: uint(d.Get("user_limit").(int)), false: channel.UserLimit}[d.HasChange("user_limit")] + bitRate = map[bool]int{true: int(d.Get("bitrate").(int)), false: channel.Bitrate}[d.HasChange("bitrate")] + userLimit = map[bool]int{true: int(d.Get("user_limit").(int)), false: channel.UserLimit}[d.HasChange("user_limit")] } } if channelType != "category" && d.HasChange("category") { - id := getId(d.Get("category").(string)) - parentId = map[bool]*disgord.Snowflake{true: &id, false: nil}[d.Get("category").(string) != ""] + id := d.Get("category").(string) + parentId = map[bool]string{true: id, false: ""}[d.Get("category").(string) != ""] } - - channel, err := client.Channel(channel.ID).Update(&disgord.UpdateChannel{ - Name: &name, + channel, err := client.ChannelEditComplex(d.Id(), &discordgo.ChannelEdit{ + Name: name, Position: &position, - Topic: &topic, + Topic: topic, NSFW: &nsfw, - Bitrate: &bitRate, - UserLimit: &userLimit, + Bitrate: bitRate, + UserLimit: userLimit, ParentID: parentId, - }) + }, discordgo.WithContext(ctx)) if err != nil { return diag.Errorf("Failed to update channel %s: %s", d.Id(), err.Error()) } if channelType != "category" { if v, ok := d.GetOk("sync_perms_with_category"); ok && v.(bool) { - if channel.ParentID.IsZero() { - return append(diags, diag.Errorf("Can't sync permissions with category. Channel (%s) doesn't have a category", channel.ID.String())...) + if channel.ParentID == "" { + return append(diags, diag.Errorf("Can't sync permissions with category. Channel (%s) doesn't have a category", channel.ID)...) } - parent, err := client.Channel(channel.ParentID).Get() + parent, err := client.Channel(channel.ParentID, discordgo.WithContext(ctx)) if err != nil { - return append(diags, diag.Errorf("Can't sync permissions with category. Channel (%s) doesn't have a category", channel.ID.String())...) + return append(diags, diag.Errorf("Can't sync permissions with category. Channel (%s) doesn't have a category", channel.ID)...) } if err = syncChannelPermissions(client, ctx, parent, channel); err != nil { - return append(diags, diag.Errorf("Can't sync permissions with category: %s", channel.ID.String())...) + return append(diags, diag.Errorf("Can't sync permissions with category: %s", channel.ID)...) } } } @@ -329,9 +340,9 @@ func resourceChannelUpdate(ctx context.Context, d *schema.ResourceData, m interf func resourceChannelDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { var diags diag.Diagnostics - client := m.(*Context).Client + client := m.(*Context).Session - _, err := client.Channel(getId(d.Id())).Delete() + _, err := client.ChannelDelete(d.Id(), discordgo.WithContext(ctx)) if err != nil { return diag.Errorf("Failed to delete channel %s: %s", d.Id(), err.Error()) } diff --git a/discord/resource_discord_channel_permission.go b/discord/resource_discord_channel_permission.go index 3b54d62..548aa4f 100644 --- a/discord/resource_discord_channel_permission.go +++ b/discord/resource_discord_channel_permission.go @@ -1,11 +1,13 @@ package discord import ( + "fmt" + "github.com/bwmarrin/discordgo" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" + "strconv" + "log" - "github.com/andersfylling/disgord" - "github.com/andersfylling/snowflake/v5" - "github.com/hashicorp/go-cty/cty" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "golang.org/x/net/context" @@ -28,18 +30,10 @@ func resourceDiscordChannelPermission() *schema.Resource { ForceNew: true, }, "type": { - Type: schema.TypeString, - ForceNew: true, - Required: true, - ValidateDiagFunc: func(val interface{}, path cty.Path) (diags diag.Diagnostics) { - v := val.(string) - - if v != "role" && v != "user" { - diags = append(diags, diag.Errorf("%s is not a valid type. Must be \"role\" or \"user\"", v)...) - } - - return diags - }, + Type: schema.TypeString, + ForceNew: true, + Required: true, + ValidateFunc: validation.StringInSlice([]string{"role", "user"}, false), }, "overwrite_id": { ForceNew: true, @@ -62,20 +56,18 @@ func resourceDiscordChannelPermission() *schema.Resource { func resourceChannelPermissionCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { var diags diag.Diagnostics - client := m.(*Context).Client + client := m.(*Context).Session - channelId := getId(d.Get("channel_id").(string)) - overwriteId := getId(d.Get("overwrite_id").(string)) + channelId := d.Get("channel_id").(string) + overwriteId := d.Get("overwrite_id").(string) permissionType, _ := getDiscordChannelPermissionType(d.Get("type").(string)) - - if err := client.Channel(channelId).UpdatePermissions(overwriteId, &disgord.UpdateChannelPermissions{ - Allow: disgord.PermissionBit(d.Get("allow").(int)), - Deny: disgord.PermissionBit(d.Get("deny").(int)), - Type: permissionType, - }); err != nil { - return diag.Errorf("Failed to update channel permissions %s: %s", channelId.String(), err.Error()) + if err := client.ChannelPermissionSet( + channelId, overwriteId, permissionType, + int64(d.Get("allow").(int)), + int64(d.Get("deny").(int)), discordgo.WithContext(ctx)); err != nil { + return diag.Errorf("Failed to update channel permissions %s: %s", channelId, err.Error()) } else { - d.SetId(generateThreePartId(channelId.String(), overwriteId.String(), d.Get("type").(string))) + d.SetId(generateThreePartId(channelId, overwriteId, d.Get("type").(string))) return diags } @@ -83,30 +75,31 @@ func resourceChannelPermissionCreate(ctx context.Context, d *schema.ResourceData func resourceChannelPermissionRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { var diags diag.Diagnostics - client := m.(*Context).Client + client := m.(*Context).Session - var channelId, overwriteId snowflake.Snowflake - var permissionType uint + channelId := d.Get("channel_id").(string) + overwriteId := d.Get("overwrite_id").(string) + var permissionType discordgo.PermissionOverwriteType cId, oId, pt, err := parseThreeIds(d.Id()) if err != nil { log.Default().Printf("Unable to parse IDs out of the resource ID. Falling back on legacy config behavior.") - channelId = getId(d.Get("channel_id").(string)) - overwriteId = getId(d.Get("overwrite_id").(string)) + channelId = d.Get("channel_id").(string) + overwriteId = d.Get("overwrite_id").(string) permissionType, _ = getDiscordChannelPermissionType(d.Get("type").(string)) } else { - channelId = getId(cId) - overwriteId = getId(oId) + channelId = cId + overwriteId = oId permissionType, _ = getDiscordChannelPermissionType(pt) - d.Set("channel_id", channelId.String()) - d.Set("overwrite_id", overwriteId.String()) + d.Set("channel_id", channelId) + d.Set("overwrite_id", overwriteId) d.Set("type", pt) } - channel, err := client.Channel(channelId).Get() + channel, err := client.Channel(channelId, discordgo.WithContext(ctx)) if err != nil { - return diag.Errorf("Failed to find channel %s: %s", channelId.String(), err.Error()) + return diag.Errorf("Failed to find channel %s: %s", channelId, err.Error()) } for _, x := range channel.PermissionOverwrites { @@ -122,32 +115,39 @@ func resourceChannelPermissionRead(ctx context.Context, d *schema.ResourceData, func resourceChannelPermissionUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { var diags diag.Diagnostics - client := m.(*Context).Client + client := m.(*Context).Session - channelId := getId(d.Get("channel_id").(string)) - overwriteId := getId(d.Get("overwrite_id").(string)) + channelId := d.Get("channel_id").(string) + overwriteId := d.Get("overwrite_id").(string) permissionType, _ := getDiscordChannelPermissionType(d.Get("type").(string)) - if err := client.Channel(channelId).UpdatePermissions(overwriteId, &disgord.UpdateChannelPermissions{ - Allow: disgord.PermissionBit(d.Get("allow").(int)), - Deny: disgord.PermissionBit(d.Get("deny").(int)), - Type: uint(permissionType), - }); err != nil { - return diag.Errorf("Failed to update channel permissions %s: %s", channelId.String(), err.Error()) + if err := client.ChannelPermissionSet( + channelId, overwriteId, permissionType, + d.Get("allow").(int64), + d.Get("deny").(int64), discordgo.WithContext(ctx)); err != nil { + return diag.Errorf("Failed to update channel permissions %s: %s", channelId, err.Error()) } else { + d.SetId(strconv.Itoa( + Hashcode( + fmt.Sprintf( + "%s:%s:%s", channelId, overwriteId, d.Get("type").(string), + ), + ), + ), + ) return diags } } func resourceChannelPermissionDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { var diags diag.Diagnostics - client := m.(*Context).Client + client := m.(*Context).Session - channelId := getId(d.Get("channel_id").(string)) - overwriteId := getId(d.Get("overwrite_id").(string)) + channelId := d.Get("channel_id").(string) + overwriteId := d.Get("overwrite_id").(string) - if err := client.Channel(channelId).DeletePermission(overwriteId); err != nil { - return diag.Errorf("Failed to delete channel permissions %s: %s", channelId.String(), err.Error()) + if err := client.ChannelPermissionDelete(channelId, overwriteId, discordgo.WithContext(ctx)); err != nil { + return diag.Errorf("Failed to delete channel permissions %s: %s", channelId, err.Error()) } else { return diags } diff --git a/discord/resource_discord_channel_permission_test.go b/discord/resource_discord_channel_permission_test.go new file mode 100644 index 0000000..36cfe80 --- /dev/null +++ b/discord/resource_discord_channel_permission_test.go @@ -0,0 +1,47 @@ +package discord + +import ( + "fmt" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "os" + "testing" +) + +func TestAccResourceDiscordChannelPermission(t *testing.T) { + testChannelID := os.Getenv("DISCORD_TEST_CHANNEL_ID") + testServerID := os.Getenv("DISCORD_TEST_SERVER_ID") + testRoleID := os.Getenv("DISCORD_TEST_ROLE_ID") + if testChannelID == "" || testServerID == "" || testRoleID == "" { + t.Skip("DISCORD_TEST_CHANNEL_ID envvar must be set for acceptance tests") + } + name := "discord_channel_permission.example" + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProviderFactories: providerFactories, + Steps: []resource.TestStep{ + { + Config: testAccResourceDiscordChannelPermission(testServerID, testChannelID, testRoleID), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(name, "channel_id", testChannelID), + resource.TestCheckResourceAttr(name, "type", "role"), + resource.TestCheckResourceAttr(name, "overwrite_id", testRoleID), + resource.TestCheckResourceAttr(name, "allow", "1024"), + ), + }, + }, + }) +} + +func testAccResourceDiscordChannelPermission(serverID, channelID, roleID string) string { + return fmt.Sprintf(` + data "discord_role" "example" { + server_id = "%[1]s" + role_id = "%[2]s" + } + resource "discord_channel_permission" "example" { + channel_id = "%[3]s" + type = "role" + overwrite_id = data.discord_role.example.role_id + allow = 1024 + }`, serverID, roleID, channelID) +} diff --git a/discord/resource_discord_invite.go b/discord/resource_discord_invite.go index f7c5e92..e38bc14 100644 --- a/discord/resource_discord_invite.go +++ b/discord/resource_discord_invite.go @@ -1,7 +1,7 @@ package discord import ( - "github.com/andersfylling/disgord" + "github.com/bwmarrin/discordgo" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "golang.org/x/net/context" @@ -44,7 +44,7 @@ func resourceDiscordInvite() *schema.Resource { Optional: true, }, "code": { - Type: schema.TypeBool, + Type: schema.TypeString, Computed: true, }, }, @@ -53,16 +53,16 @@ func resourceDiscordInvite() *schema.Resource { func resourceInviteCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { var diags diag.Diagnostics - client := m.(*Context).Client + client := m.(*Context).Session - channelId := getId(d.Get("channel_id").(string)) + channelId := d.Get("channel_id").(string) - if invite, err := client.Channel(channelId).CreateInvite(&disgord.CreateInvite{ + if invite, err := client.ChannelInviteCreate(channelId, discordgo.Invite{ MaxAge: d.Get("max_age").(int), MaxUses: d.Get("max_uses").(int), Temporary: d.Get("temporary").(bool), Unique: d.Get("unique").(bool), - }); err != nil { + }, discordgo.WithContext(ctx)); err != nil { return diag.Errorf("Failed to create a invite: %s", err.Error()) } else { d.SetId(invite.Code) @@ -74,9 +74,9 @@ func resourceInviteCreate(ctx context.Context, d *schema.ResourceData, m interfa func resourceInviteRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { var diags diag.Diagnostics - client := m.(*Context).Client + client := m.(*Context).Session - if invite, err := client.Invite(d.Id()).Get(false); err != nil { + if invite, err := client.Invite(d.Id(), discordgo.WithContext(ctx)); err != nil { d.SetId("") } else { d.Set("code", invite.Code) @@ -87,9 +87,9 @@ func resourceInviteRead(ctx context.Context, d *schema.ResourceData, m interface func resourceInviteDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { var diags diag.Diagnostics - client := m.(*Context).Client + client := m.(*Context).Session - if _, err := client.Invite(d.Id()).Delete(); err != nil { + if _, err := client.InviteDelete(d.Id(), discordgo.WithContext(ctx)); err != nil { return diag.FromErr(err) } else { return diags diff --git a/discord/resource_discord_invite_test.go b/discord/resource_discord_invite_test.go new file mode 100644 index 0000000..e0140b3 --- /dev/null +++ b/discord/resource_discord_invite_test.go @@ -0,0 +1,44 @@ +package discord + +import ( + "fmt" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "os" + "testing" +) + +func TestAccResourceDiscordInvite(t *testing.T) { + testChannelID := os.Getenv("DISCORD_TEST_CHANNEL_ID") + if testChannelID == "" { + t.Skip("DISCORD_TEST_CHANNEL_ID envvar must be set for acceptance tests") + } + name := "discord_invite.example" + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProviderFactories: providerFactories, + Steps: []resource.TestStep{ + { + Config: testAccResourceDiscordInvite(testChannelID), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(name, "channel_id", testChannelID), + resource.TestCheckResourceAttr(name, "max_age", "86400"), + resource.TestCheckResourceAttr(name, "max_uses", "1"), + resource.TestCheckResourceAttr(name, "temporary", "true"), + resource.TestCheckResourceAttr(name, "unique", "false"), + resource.TestCheckResourceAttrSet(name, "code"), + ), + }, + }, + }) +} + +func testAccResourceDiscordInvite(channelID string) string { + return fmt.Sprintf(` + resource "discord_invite" "example" { + channel_id = "%[1]s" + max_age = 86400 + max_uses = 1 + temporary = true + unique = false + }`, channelID) +} diff --git a/discord/resource_discord_member_roles.go b/discord/resource_discord_member_roles.go index e18b49b..97a9204 100644 --- a/discord/resource_discord_member_roles.go +++ b/discord/resource_discord_member_roles.go @@ -2,18 +2,17 @@ package discord import ( "encoding/json" + "github.com/bwmarrin/discordgo" "log" - "github.com/andersfylling/disgord" - "github.com/andersfylling/snowflake/v5" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "golang.org/x/net/context" ) type RoleSchema struct { - RoleId disgord.Snowflake `json:"role_id"` - HasRole bool `json:"has_role"` + RoleId string `json:"role_id"` + HasRole bool `json:"has_role"` } func convertToRoleSchema(v interface{}) (*RoleSchema, error) { @@ -69,16 +68,16 @@ func resourceDiscordMemberRoles() *schema.Resource { func resourceMemberRolesCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { var diags diag.Diagnostics - client := m.(*Context).Client + client := m.(*Context).Session - serverId := getId(d.Get("server_id").(string)) - userId := getId(d.Get("user_id").(string)) + serverId := d.Get("server_id").(string) + userId := d.Get("user_id").(string) - if _, err := client.Guild(serverId).Member(userId).Get(); err != nil { - return diag.Errorf("Could not get member %s in %s: %s", userId.String(), serverId.String(), err.Error()) + if _, err := client.GuildMember(serverId, userId, discordgo.WithContext(ctx)); err != nil { + return diag.Errorf("Could not get member %s in %s: %s", userId, serverId, err.Error()) } - d.SetId(generateTwoPartId(serverId.String(), userId.String())) + d.SetId(generateTwoPartId(serverId, userId)) diags = append(diags, resourceMemberRolesRead(ctx, d, m)...) diags = append(diags, resourceMemberRolesUpdate(ctx, d, m)...) @@ -88,23 +87,23 @@ func resourceMemberRolesCreate(ctx context.Context, d *schema.ResourceData, m in func resourceMemberRolesRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { var diags diag.Diagnostics - client := m.(*Context).Client + client := m.(*Context).Session // parse server ID and userID out of the ID: - var serverId, userId snowflake.Snowflake + var serverId, userId string sId, uId, err := parseTwoIds(d.Id()) if err != nil { log.Default().Printf("Unable to parse IDs out of the resource ID. Falling back on legacy config behavior.") - serverId = getId(d.Get("server_id").(string)) - userId = getId(d.Get("user_id").(string)) + serverId = d.Get("server_id").(string) + userId = d.Get("user_id").(string) } else { - serverId = getId(sId) - userId = getId(uId) + serverId = sId + userId = uId } - member, err := client.Guild(serverId).Member(userId).Get() + member, err := client.GuildMember(serverId, userId, discordgo.WithContext(ctx)) if err != nil { - return diag.Errorf("Could not get member %s in %s: %s", userId.String(), serverId.String(), err.Error()) + return diag.Errorf("Could not get member %s in %s: %s", userId, serverId, err.Error()) } items := d.Get("role").(*schema.Set).List() @@ -112,48 +111,48 @@ func resourceMemberRolesRead(ctx context.Context, d *schema.ResourceData, m inte for _, r := range items { v, _ := convertToRoleSchema(r) - if hasRole(member, v.RoleId) { roles = append(roles, &RoleSchema{RoleId: v.RoleId, HasRole: true}) } else { roles = append(roles, &RoleSchema{RoleId: v.RoleId, HasRole: false}) } } + d.Set("role", roles) return diags } func resourceMemberRolesUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { var diags diag.Diagnostics - client := m.(*Context).Client + client := m.(*Context).Session - serverId := getId(d.Get("server_id").(string)) - userId := getId(d.Get("user_id").(string)) + serverId := d.Get("server_id").(string) + userId := d.Get("user_id").(string) - member, err := client.Guild(serverId).Member(userId).Get() + member, err := client.GuildMember(serverId, userId, discordgo.WithContext(ctx)) if err != nil { - return diag.Errorf("Could not get member %s in %s: %s", userId.String(), serverId.String(), err.Error()) + return diag.Errorf("Could not get member %s in %s: %s", userId, serverId, err.Error()) } - old, new := d.GetChange("role") - oldItems := old.(*schema.Set).List() - items := new.(*schema.Set).List() + oldRole, newRole := d.GetChange("role") + oldItems := oldRole.(*schema.Set).List() + items := newRole.(*schema.Set).List() roles := member.Roles for _, r := range items { v, _ := convertToRoleSchema(r) - hasRole := hasRole(member, v.RoleId) + memberHasRole := hasRole(member, v.RoleId) // If it's supposed to have the role, and it does, continue - if hasRole && v.HasRole { + if memberHasRole && v.HasRole { continue } // If it's supposed to have the role, and it doesn't, add it - if v.HasRole && !hasRole { + if v.HasRole && !memberHasRole { roles = append(roles, v.RoleId) } // If it's not supposed to have the role, and it does, remove it - if !v.HasRole && hasRole { + if !v.HasRole && memberHasRole { roles = removeRoleById(roles, v.RoleId) } } @@ -166,10 +165,10 @@ func resourceMemberRolesUpdate(ctx context.Context, d *schema.ResourceData, m in } } - if _, err := client.Guild(serverId).Member(userId).Update(&disgord.UpdateMember{ + if _, err := client.GuildMemberEdit(serverId, userId, &discordgo.GuildMemberParams{ Roles: &roles, - }); err != nil { - return diag.Errorf("Failed to edit member %s: %s", userId.String(), err.Error()) + }, discordgo.WithContext(ctx)); err != nil { + return diag.Errorf("Failed to edit member %s: %s", userId, err.Error()) } return diags @@ -188,13 +187,13 @@ func wasRemoved(items []interface{}, v *RoleSchema) bool { func resourceMemberRolesDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { var diags diag.Diagnostics - client := m.(*Context).Client - serverId := getId(d.Get("server_id").(string)) - userId := getId(d.Get("user_id").(string)) + client := m.(*Context).Session + serverId := d.Get("server_id").(string) + userId := d.Get("user_id").(string) - member, err := client.Guild(serverId).Member(userId).Get() + member, err := client.GuildMember(serverId, userId, discordgo.WithContext(ctx)) if err != nil { - return diag.Errorf("Could not get member %s in %s: %s", userId.String(), serverId.String(), err.Error()) + return diag.Errorf("Could not get member %s in %s: %s", userId, serverId, err.Error()) } items := d.Get("role").(*schema.Set).List() @@ -209,9 +208,11 @@ func resourceMemberRolesDelete(ctx context.Context, d *schema.ResourceData, m in } } - client.Guild(serverId).Member(userId).Update(&disgord.UpdateMember{ + if _, err := client.GuildMemberEdit(serverId, userId, &discordgo.GuildMemberParams{ Roles: &roles, - }) + }, discordgo.WithContext(ctx)); err != nil { + return diag.Errorf("Failed to delete member roles %s: %s", userId, err.Error()) + } return diags } diff --git a/discord/resource_discord_message.go b/discord/resource_discord_message.go index 52b9953..f78f584 100644 --- a/discord/resource_discord_message.go +++ b/discord/resource_discord_message.go @@ -1,12 +1,10 @@ package discord import ( - "log" - "os" + "github.com/bwmarrin/discordgo" "strings" "time" - "github.com/andersfylling/disgord" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "golang.org/x/net/context" @@ -253,45 +251,44 @@ func resourceDiscordMessage() *schema.Resource { func resourceMessageCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { var diags diag.Diagnostics - client := m.(*Context).Client + client := m.(*Context).Session - channelId := getId(d.Get("channel_id").(string)) + channelId := d.Get("channel_id").(string) - embeds := make([]*disgord.Embed, 0, 1) + embeds := make([]*discordgo.MessageEmbed, 0, 1) if v, ok := d.GetOk("embed"); ok { if embed, err := buildEmbed(v.([]interface{})); err != nil { - return diag.Errorf("Failed to create message in %s: %s", channelId.String(), err.Error()) + return diag.Errorf("Failed to create message in %s: %s", channelId, err.Error()) } else { embeds = append(embeds, embed) } } - - message, err := client.Channel(channelId).CreateMessage(&disgord.CreateMessage{ + message, err := client.ChannelMessageSendComplex(channelId, &discordgo.MessageSend{ Content: d.Get("content").(string), - Tts: d.Get("tts").(bool), Embeds: embeds, - }) + TTS: d.Get("tts").(bool), + }, discordgo.WithContext(ctx)) if err != nil { - return diag.Errorf("Failed to create message in %s: %s", channelId.String(), err.Error()) + return diag.Errorf("Failed to create message in %s: %s", channelId, err.Error()) } - d.SetId(message.ID.String()) + d.SetId(message.ID) d.Set("type", int(message.Type)) d.Set("timestamp", message.Timestamp.Format(time.RFC3339)) - d.Set("author", message.Author.ID.String()) + d.Set("author", message.Author.ID) if len(message.Embeds) > 0 { d.Set("embed", unbuildEmbed(message.Embeds[0])) } else { d.Set("embed", nil) } - if !message.GuildID.IsZero() { - d.Set("server_id", message.GuildID.String()) + if message.GuildID != "" { + d.Set("server_id", message.GuildID) } if d.Get("pinned").(bool) { - err = client.Channel(channelId).Message(message.ID).Pin() - if err != nil { - diags = append(diags, diag.Errorf("Failed to pin message %s in %s: %s", message.ID.String(), channelId.String(), err.Error())...) + pinError := client.ChannelMessagePin(channelId, message.ID, discordgo.WithContext(ctx)) + if pinError != nil { + diags = append(diags, diag.Errorf("Failed to pin message %s in %s: %s", message.ID, channelId, err.Error())...) } } @@ -300,67 +297,61 @@ func resourceMessageCreate(ctx context.Context, d *schema.ResourceData, m interf func resourceMessageRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { var diags diag.Diagnostics - client := m.(*Context).Client + client := m.(*Context).Session - channelId := getId(d.Get("channel_id").(string)) - messageId := getId(d.Id()) - message, err := client.Channel(channelId).Message(messageId).Get() + channelId := d.Get("channel_id").(string) + messageId := d.Id() + message, err := client.ChannelMessage(channelId, messageId, discordgo.WithContext(ctx)) if err != nil { - return diag.Errorf("Failed to fetch message %s in %s: %s", messageId.String(), channelId.String(), err.Error()) + return diag.Errorf("Failed to fetch message %s in %s: %s", messageId, channelId, err.Error()) } - if !message.GuildID.IsZero() { - d.Set("server_id", message.GuildID.String()) + if message.GuildID != "" { + d.Set("server_id", message.GuildID) } d.Set("type", int(message.Type)) - d.Set("tts", message.Tts) + d.Set("tts", message.TTS) d.Set("timestamp", message.Timestamp.Format(time.RFC3339)) - d.Set("author", message.Author.ID.String()) + d.Set("author", message.Author.ID) d.Set("content", message.Content) d.Set("pinned", message.Pinned) if len(message.Embeds) > 0 { d.Set("embed", unbuildEmbed(message.Embeds[0])) } - d.Set("edited_timestamp", message.EditedTimestamp.Format(time.RFC3339)) + if message.EditedTimestamp != nil { + d.Set("edited_timestamp", message.EditedTimestamp.Format(time.RFC3339)) + } return diags } func resourceMessageUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { - f, err := os.OpenFile("text.log", - os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) - if err != nil { - log.Println(err) - } - defer f.Close() - - logger := log.New(f, "", log.LstdFlags) var diags diag.Diagnostics - client := m.(*Context).Client + client := m.(*Context).Session - channelId := getId(d.Get("channel_id").(string)) - messageId := getId(d.Id()) + channelId := d.Get("channel_id").(string) + messageId := d.Id() var content string - builder := client.Channel(channelId).Message(messageId) - message, _ := builder.Get() + message, err := client.ChannelMessage(channelId, messageId, discordgo.WithContext(ctx)) + if err != nil { + return diag.Errorf("Failed to fetch message %s in %s: %s", messageId, channelId, err.Error()) + } if d.HasChange("content") { - logger.Printf("old: %#v\n\n", message.Content) - logger.Printf("new: %#v\n\n", d.Get("content").(string)) content = d.Get("content").(string) } else { content = message.Content } - embeds := make([]*disgord.Embed, 0, 1) + embeds := make([]*discordgo.MessageEmbed, 0, 1) if d.HasChange("embed") { - var embed *disgord.Embed + var embed *discordgo.MessageEmbed _, n := d.GetChange("embed") if len(n.([]interface{})) > 0 { if e, err := buildEmbed(n.([]interface{})); err != nil { - return diag.Errorf("Failed to edit message %s in %s: %s", messageId.String(), channelId.String(), err.Error()) + return diag.Errorf("Failed to edit message %s in %s: %s", messageId, channelId, err.Error()) } else { embed = e } @@ -369,32 +360,35 @@ func resourceMessageUpdate(ctx context.Context, d *schema.ResourceData, m interf embeds = append(embeds, embed) } - if _, err := builder.Update(&disgord.UpdateMessage{ + editedMessage, err := client.ChannelMessageEditComplex(&discordgo.MessageEdit{ + ID: messageId, + Channel: channelId, Content: &content, Embeds: &embeds, - }); err != nil { - return diag.Errorf("Failed to update message %s in %s: %s", channelId.String(), messageId.String(), err.Error()) + }, discordgo.WithContext(ctx)) + if err != nil { + return diag.Errorf("Failed to update message %s in %s: %s", channelId, messageId, err.Error()) } - if len(message.Embeds) > 0 { + if len(editedMessage.Embeds) > 0 { d.Set("embed", unbuildEmbed(message.Embeds[0])) } else { d.Set("embed", nil) } - d.Set("edited_timestamp", message.EditedTimestamp.Format(time.RFC3339)) + d.Set("edited_timestamp", editedMessage.EditedTimestamp.Format(time.RFC3339)) return diags } func resourceMessageDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { var diags diag.Diagnostics - client := m.(*Context).Client + client := m.(*Context).Session - channelId := getId(d.Get("channel_id").(string)) - messageId := getId(d.Id()) - if err := client.Channel(channelId).Message(messageId).Delete(); err != nil { - return diag.Errorf("Failed to delete message %s in %s: %s", messageId.String(), channelId.String(), err.Error()) + channelId := d.Get("channel_id").(string) + messageId := d.Id() + if err := client.ChannelMessageDelete(channelId, messageId, discordgo.WithContext(ctx)); err != nil { + return diag.Errorf("Failed to delete message %s in %s: %s", messageId, channelId, err.Error()) } else { return diags } diff --git a/discord/resource_discord_message_test.go b/discord/resource_discord_message_test.go new file mode 100644 index 0000000..c408ffd --- /dev/null +++ b/discord/resource_discord_message_test.go @@ -0,0 +1,82 @@ +package discord + +import ( + "fmt" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "os" + "testing" +) + +func TestAccResourceDiscordMessageContent(t *testing.T) { + testChannelID := os.Getenv("DISCORD_TEST_CHANNEL_ID") + if testChannelID == "" { + t.Skip("DISCORD_TEST_CHANNEL_ID envvar must be set for acceptance tests") + } + name := "discord_message.example" + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProviderFactories: providerFactories, + Steps: []resource.TestStep{ + { + Config: testAccResourceDiscordMessageContent(testChannelID), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(name, "channel_id", testChannelID), + resource.TestCheckResourceAttr(name, "content", "Hello, World from Terraform!"), + resource.TestCheckResourceAttr(name, "tts", "false"), + ), + }, + }, + }) +} + +func TestAccResourceDiscordMessageEmbed(t *testing.T) { + testChannelID := os.Getenv("DISCORD_TEST_CHANNEL_ID") + if testChannelID == "" { + t.Skip("DISCORD_TEST_CHANNEL_ID envvar must be set for acceptance tests") + } + name := "discord_message.example" + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProviderFactories: providerFactories, + Steps: []resource.TestStep{ + { + Config: testAccResourceDiscordEmbed(testChannelID), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(name, "channel_id", testChannelID), + resource.TestCheckResourceAttr(name, "embed.#", "1"), + resource.TestCheckResourceAttr(name, "embed.0.title", "Hello, World from Terraform!"), + resource.TestCheckResourceAttr(name, "embed.0.description", "This is a test message from Terraform!"), + resource.TestCheckResourceAttr(name, "embed.0.color", "65280"), + resource.TestCheckResourceAttr(name, "embed.0.footer.0.text", "This is a test footer from Terraform!"), + ), + }, + }, + }) +} + +func testAccResourceDiscordMessageContent(channelID string) string { + return fmt.Sprintf(` + resource "discord_message" "example" { + channel_id = "%[1]s" + content = "Hello, World from Terraform!" + tts = false + }`, channelID) +} + +func testAccResourceDiscordEmbed(channelID string) string { + return fmt.Sprintf(` + data "discord_color" "green" { + hex = "#00ff00" + } + resource "discord_message" "example" { + channel_id = "%[1]s" + embed { + title = "Hello, World from Terraform!" + description = "This is a test message from Terraform!" + color = data.discord_color.green.dec + footer { + text = "This is a test footer from Terraform!" + } + } + }`, channelID) +} diff --git a/discord/resource_discord_news_channel_test.go b/discord/resource_discord_news_channel_test.go new file mode 100644 index 0000000..5d96b16 --- /dev/null +++ b/discord/resource_discord_news_channel_test.go @@ -0,0 +1,45 @@ +package discord + +import ( + "fmt" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "os" + "testing" +) + +func TestAccResourceDiscordNewsChannel(t *testing.T) { + testServerID := os.Getenv("DISCORD_TEST_SERVER_ID") + if testServerID == "" { + t.Skip("DISCORD_TEST_SERVER_ID envvar must be set for acceptance tests") + } + name := "discord_news_channel.example" + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProviderFactories: providerFactories, + Steps: []resource.TestStep{ + { + Config: testAccResourceDiscordNewsChannel(testServerID), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(name, "server_id", testServerID), + resource.TestCheckResourceAttr(name, "name", "terraform-news-channel"), + resource.TestCheckResourceAttr(name, "type", "news"), + resource.TestCheckResourceAttr(name, "position", "1"), + resource.TestCheckResourceAttrSet(name, "channel_id"), + resource.TestCheckResourceAttr(name, "topic", "Testing news channel"), + resource.TestCheckResourceAttr(name, "sync_perms_with_category", "false"), + ), + }, + }, + }) +} + +func testAccResourceDiscordNewsChannel(serverID string) string { + return fmt.Sprintf(` + resource "discord_news_channel" "example" { + server_id = "%[1]s" + name = "terraform-news-channel" + position = 1 + topic = "Testing news channel" + sync_perms_with_category = false + }`, serverID) +} diff --git a/discord/resource_discord_role.go b/discord/resource_discord_role.go index 40b71ec..30e6b78 100644 --- a/discord/resource_discord_role.go +++ b/discord/resource_discord_role.go @@ -1,11 +1,10 @@ package discord import ( - "fmt" - - "github.com/andersfylling/disgord" + "github.com/bwmarrin/discordgo" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "golang.org/x/net/context" ) @@ -54,20 +53,11 @@ func resourceDiscordRole() *schema.Resource { ForceNew: false, }, "position": { - Type: schema.TypeInt, - Optional: true, - Default: 1, - ForceNew: false, - - ValidateFunc: func(val interface{}, key string) (warns []string, errors []error) { - v := val.(int) - - if v < 0 { - errors = append(errors, fmt.Errorf("position must be greater than 0, got: %d", v)) - } - - return - }, + Type: schema.TypeInt, + Optional: true, + Default: 1, + ForceNew: false, + ValidateFunc: validation.IntAtLeast(1), }, "managed": { Type: schema.TypeBool, @@ -78,11 +68,11 @@ func resourceDiscordRole() *schema.Resource { } func resourceRoleImport(ctx context.Context, data *schema.ResourceData, i interface{}) ([]*schema.ResourceData, error) { - if serverId, roleId, err := getBothIds(data.Id()); err != nil { + if serverId, roleId, err := parseTwoIds(data.Id()); err != nil { return nil, err } else { - data.SetId(roleId.String()) - data.Set("server_id", serverId.String()) + data.SetId(roleId) + data.Set("server_id", serverId) return schema.ImportStatePassthroughContext(ctx, data, i) } @@ -90,27 +80,27 @@ func resourceRoleImport(ctx context.Context, data *schema.ResourceData, i interf func resourceRoleCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { var diags diag.Diagnostics - client := m.(*Context).Client + client := m.(*Context).Session - serverId := getId(d.Get("server_id").(string)) - server, err := client.Guild(serverId).Get() + serverId := d.Get("server_id").(string) + server, err := client.Guild(serverId) if err != nil { return diag.Errorf("Server does not exist with that ID: %s", serverId) } - - role, err := client.Guild(serverId).CreateRole(&disgord.CreateGuildRole{ + role, err := client.GuildRoleCreate(serverId, &discordgo.RoleParams{ Name: d.Get("name").(string), - Permissions: uint64(d.Get("permissions").(int)), - Color: uint(d.Get("color").(int)), - Hoist: d.Get("hoist").(bool), - Mentionable: d.Get("mentionable").(bool), - }) + Permissions: Int64Ptr(int64(d.Get("permissions").(int))), + Color: IntPtr(d.Get("color").(int)), + Hoist: BoolPtr(d.Get("hoist").(bool)), + Mentionable: BoolPtr(d.Get("mentionable").(bool)), + }, discordgo.WithContext(ctx)) + if err != nil { - return diag.Errorf("Failed to create role for %s: %s", serverId.String(), err.Error()) + return diag.Errorf("Failed to create role for %s: %s", serverId, err.Error()) } if newPosition, ok := d.GetOk("position"); ok { - var oldRole *disgord.Role + var oldRole *discordgo.Role for _, r := range server.Roles { if r.Position == newPosition.(int) { oldRole = r @@ -118,20 +108,20 @@ func resourceRoleCreate(ctx context.Context, d *schema.ResourceData, m interface } } - param := []disgord.UpdateGuildRolePositions{{ID: role.ID, Position: newPosition.(int)}} + param := []*discordgo.Role{{ID: role.ID, Position: newPosition.(int)}} if oldRole != nil { - param = append(param, disgord.UpdateGuildRolePositions{ID: oldRole.ID, Position: role.Position}) + param = append(param, &discordgo.Role{ID: oldRole.ID, Position: role.Position}) } - if _, err := client.Guild(serverId).UpdateRolePositions(param); err != nil { + if _, err := client.GuildRoleReorder(serverId, param, discordgo.WithContext(ctx)); err != nil { diags = append(diags, diag.Errorf("Failed to re-order roles: %s", err.Error())...) } else { d.Set("position", newPosition) } } - d.SetId(role.ID.String()) - d.Set("server_id", server.ID.String()) + d.SetId(role.ID) + d.Set("server_id", server.ID) d.Set("managed", role.Managed) return diags @@ -139,60 +129,58 @@ func resourceRoleCreate(ctx context.Context, d *schema.ResourceData, m interface func resourceRoleRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { var diags diag.Diagnostics - client := m.(*Context).Client + client := m.(*Context).Session - serverId := getId(d.Get("server_id").(string)) - server, err := client.Guild(serverId).Get() - if err != nil { - return diag.Errorf("Failed to fetch server %s: %s", serverId.String(), err.Error()) - } + role, err := getRole(ctx, client, d.Get("server_id").(string), d.Id()) - if role, err := server.Role(getId(d.Id())); err != nil { + if err != nil { return diag.Errorf("Failed to fetch role %s: %s", d.Id(), err.Error()) - } else { - d.Set("name", role.Name) - d.Set("position", role.Position) - d.Set("color", role.Color) - d.Set("hoist", role.Hoist) - d.Set("mentionable", role.Mentionable) - d.Set("permissions", role.Permissions) - d.Set("managed", role.Managed) - - return diags } + + d.Set("name", role.Name) + d.Set("position", role.Position) + d.Set("color", role.Color) + d.Set("hoist", role.Hoist) + d.Set("mentionable", role.Mentionable) + d.Set("permissions", role.Permissions) + d.Set("managed", role.Managed) + + return diags + } func resourceRoleUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { var diags diag.Diagnostics - client := m.(*Context).Client + client := m.(*Context).Session - serverId := getId(d.Get("server_id").(string)) - server, err := client.Guild(serverId).Get() + serverId := d.Get("server_id").(string) + server, err := client.Guild(serverId) if err != nil { - return diag.Errorf("Failed to fetch server %s: %s", serverId.String(), err.Error()) + return diag.Errorf("Failed to fetch server %s: %s", serverId, err.Error()) } - roleId := getId(d.Id()) - role, err := server.Role(roleId) + roleId := d.Id() + role, err := getRole(ctx, client, serverId, roleId) if err != nil { return diag.Errorf("Failed to fetch role %s: %s", d.Id(), err.Error()) } if d.HasChange("position") { _, newPosition := d.GetChange("position") - var oldRole *disgord.Role + var oldRole *discordgo.Role for _, r := range server.Roles { if r.Position == newPosition.(int) { oldRole = r break } } - param := []disgord.UpdateGuildRolePositions{{ID: roleId, Position: newPosition.(int)}} + + param := []*discordgo.Role{{ID: role.ID, Position: newPosition.(int)}} if oldRole != nil { - param = append(param, disgord.UpdateGuildRolePositions{ID: oldRole.ID, Position: role.Position}) + param = append(param, &discordgo.Role{ID: oldRole.ID, Position: role.Position}) } - if _, err := client.Guild(serverId).UpdateRolePositions(param); err != nil { + if _, err := client.GuildRoleReorder(serverId, param, discordgo.WithContext(ctx)); err != nil { diags = append(diags, diag.Errorf("Failed to re-order roles: %s", err.Error())...) } else { d.Set("position", newPosition) @@ -204,43 +192,41 @@ func resourceRoleUpdate(ctx context.Context, d *schema.ResourceData, m interface newColor int newHoist = d.Get("hoist").(bool) newMentionable = d.Get("mentionable").(bool) - newPermissions = disgord.PermissionBit(d.Get("permissions").(int)) + newPermissions = d.Get("permissions").(int64) ) if _, v := d.GetChange("color"); v.(int) > 0 { newColor = v.(int) } else { - newColor = int(role.Color) + newColor = role.Color } - if role, err := client.Guild(serverId).Role(roleId).Update(&disgord.UpdateRole{ - Name: &newName, + if role, err = client.GuildRoleEdit(serverId, roleId, &discordgo.RoleParams{ + Name: newName, Color: &newColor, Hoist: &newHoist, Mentionable: &newMentionable, Permissions: &newPermissions, - }); err != nil { + }, discordgo.WithContext(ctx)); err != nil { return diag.Errorf("Failed to update role %s: %s", d.Id(), err.Error()) - } else { - d.Set("name", role.Name) - d.Set("position", role.Position) - d.Set("color", role.Color) - d.Set("hoist", role.Hoist) - d.Set("mentionable", role.Mentionable) - d.Set("permissions", role.Permissions) - d.Set("managed", role.Managed) - - return diags } + + d.Set("name", role.Name) + d.Set("position", role.Position) + d.Set("color", role.Color) + d.Set("hoist", role.Hoist) + d.Set("mentionable", role.Mentionable) + d.Set("permissions", role.Permissions) + d.Set("managed", role.Managed) + + return diags } func resourceRoleDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { var diags diag.Diagnostics - client := m.(*Context).Client - - serverId := getId(d.Get("server_id").(string)) - roleId := getId(d.Id()) + client := m.(*Context).Session - if err := client.Guild(serverId).Role(roleId).Delete(); err != nil { + serverId := d.Get("server_id") + if err := client.GuildRoleDelete(serverId.(string), d.Id(), discordgo.WithContext(ctx)); err != nil { return diag.Errorf("Failed to delete role: %s", err.Error()) } diff --git a/discord/resource_discord_role_everyone.go b/discord/resource_discord_role_everyone.go index d0166e9..87e10b6 100644 --- a/discord/resource_discord_role_everyone.go +++ b/discord/resource_discord_role_everyone.go @@ -1,7 +1,7 @@ package discord import ( - "github.com/andersfylling/disgord" + "github.com/bwmarrin/discordgo" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "golang.org/x/net/context" @@ -40,24 +40,19 @@ func resourceDiscordRoleEveryone() *schema.Resource { func resourceRoleEveryoneImport(ctx context.Context, data *schema.ResourceData, i interface{}) ([]*schema.ResourceData, error) { data.SetId(data.Id()) - data.Set("server_id", getId(data.Id()).String()) + data.Set("server_id", data.Id()) return schema.ImportStatePassthroughContext(ctx, data, i) } func resourceRoleEveryoneRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { var diags diag.Diagnostics - client := m.(*Context).Client + client := m.(*Context).Session - serverId := getId(d.Get("server_id").(string)) - d.SetId(serverId.String()) + serverId := d.Get("server_id").(string) + d.SetId(serverId) - server, err := client.Guild(serverId).Get() - if err != nil { - return diag.Errorf("Failed to fetch server %s: %s", serverId.String(), err.Error()) - } - - if role, err := server.Role(serverId); err != nil { + if role, err := getRole(ctx, client, serverId, serverId); err != nil { return diag.Errorf("Failed to fetch role %s: %s", d.Id(), err.Error()) } else { d.Set("permissions", role.Permissions) @@ -68,14 +63,15 @@ func resourceRoleEveryoneRead(ctx context.Context, d *schema.ResourceData, m int func resourceRoleEveryoneUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { var diags diag.Diagnostics - client := m.(*Context).Client + client := m.(*Context).Session + + serverId := d.Get("server_id").(string) + d.SetId(serverId) + newPermission := int64(d.Get("permissions").(int)) - serverId := getId(d.Get("server_id").(string)) - d.SetId(serverId.String()) - newPermission := disgord.PermissionBit(d.Get("permissions").(int)) - if role, err := client.Guild(serverId).Role(serverId).Update(&disgord.UpdateRole{ + if role, err := client.GuildRoleEdit(serverId, serverId, &discordgo.RoleParams{ Permissions: &newPermission, - }); err != nil { + }, discordgo.WithContext(ctx)); err != nil { return diag.Errorf("Failed to update role %s: %s", d.Id(), err.Error()) } else { d.Set("permissions", role.Permissions) diff --git a/discord/resource_discord_role_test.go b/discord/resource_discord_role_test.go new file mode 100644 index 0000000..775479f --- /dev/null +++ b/discord/resource_discord_role_test.go @@ -0,0 +1,51 @@ +package discord + +import ( + "fmt" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "os" + "testing" +) + +func TestAccResourceDiscordRole(t *testing.T) { + testServerID := os.Getenv("DISCORD_TEST_SERVER_ID") + if testServerID == "" { + t.Skip("DISCORD_TEST_SERVER_ID envvar must be set for acceptance tests") + } + name := "discord_role.example" + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProviderFactories: providerFactories, + Steps: []resource.TestStep{ + { + Config: testAccResourceDiscordRole(testServerID), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(name, "server_id", testServerID), + resource.TestCheckResourceAttr(name, "name", "terraform-test-role"), + resource.TestCheckResourceAttr(name, "color", "65280"), + resource.TestCheckResourceAttr(name, "hoist", "true"), + resource.TestCheckResourceAttr(name, "mentionable", "true"), + resource.TestCheckResourceAttr(name, "position", "2"), + resource.TestCheckResourceAttr(name, "permissions", "1024"), + ), + }, + }, + }) +} + +func testAccResourceDiscordRole(channelID string) string { + return fmt.Sprintf(` + data "discord_color" "green" { + hex = "#00ff00" + } + + resource "discord_role" "example" { + server_id = "%[1]s" + name = "terraform-test-role" + color = data.discord_color.green.dec + hoist = true + mentionable = true + position = 2 + permissions = 1024 + }`, channelID) +} diff --git a/discord/resource_discord_server.go b/discord/resource_discord_server.go index 0f312b1..8dbbe68 100644 --- a/discord/resource_discord_server.go +++ b/discord/resource_discord_server.go @@ -3,7 +3,7 @@ package discord import ( "fmt" - "github.com/andersfylling/disgord" + "github.com/bwmarrin/discordgo" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/polds/imgbase64" @@ -15,6 +15,7 @@ func baseServerSchema() map[string]*schema.Schema { "region": { Type: schema.TypeString, Optional: true, + Computed: true, }, "verification_level": { Type: schema.TypeInt, @@ -101,6 +102,7 @@ func baseServerSchema() map[string]*schema.Schema { "owner_id": { Type: schema.TypeString, Optional: true, + Computed: true, }, } } @@ -165,7 +167,7 @@ func resourceDiscordManagedServer() *schema.Resource { func resourceServerCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { var diags diag.Diagnostics - client := m.(*Context).Client + client := m.(*Context).Session icon := "" if v, ok := d.GetOk("icon_url"); ok { @@ -176,31 +178,13 @@ func resourceServerCreate(ctx context.Context, d *schema.ResourceData, m interfa } name := d.Get("name").(string) - server, err := client.CreateGuild(name, &disgord.CreateGuild{ - Region: d.Get("region").(string), - Icon: icon, - VerificationLvl: d.Get("verification_level").(int), - DefaultMsgNotifications: disgord.DefaultMessageNotificationLvl(d.Get("default_message_notifications").(int)), - ExplicitContentFilter: disgord.ExplicitContentFilterLvl(d.Get("explicit_content_filter").(int)), - Channels: nil, - }) + // DiscordGo doesn't support creating a server with anything apart from a name. + server, err := client.GuildCreate(name, discordgo.WithContext(ctx)) if err != nil { return diag.Errorf("Failed to create server: %s", err.Error()) } - channels, err := client.Guild(server.ID).GetChannels() - if err != nil { - return diag.Errorf("Failed to fetch channels for new server: %s", err.Error()) - } - - for _, channel := range channels { - if _, err := client.Channel(channel.ID).Delete(); err != nil { - return diag.Errorf("Failed to delete channel for new server: %s", err.Error()) - } - } - splash := "" - edit := false if v, ok := d.GetOk("splash_url"); ok { splash = imgbase64.FromRemote(v.(string)) } @@ -208,52 +192,57 @@ func resourceServerCreate(ctx context.Context, d *schema.ResourceData, m interfa splash = v.(string) } if splash != "" { - edit = true } afkChannel := server.AfkChannelID if v, ok := d.GetOk("afk_channel_id"); ok { - afkChannel = disgord.ParseSnowflakeString(v.(string)) - edit = true + afkChannel = v.(string) } afkTimeOut := server.AfkTimeout if v, ok := d.GetOk("afk_timeout"); ok { // The value has been already validated, so this cast is safe. - afkTimeOut = uint(v.(int)) - edit = true + afkTimeOut = v.(int) + } + + verificationLevel := discordgo.VerificationLevel(d.Get("verification_level").(int)) + server, err = client.GuildEdit(server.ID, &discordgo.GuildParams{ + Icon: icon, + Region: d.Get("region").(string), + VerificationLevel: &verificationLevel, + DefaultMessageNotifications: d.Get("default_message_notifications").(int), + ExplicitContentFilter: d.Get("explicit_content_filter").(int), + AfkChannelID: afkChannel, + AfkTimeout: afkTimeOut, + Splash: splash, + }, discordgo.WithContext(ctx)) + if err != nil { + return diag.Errorf("Failed to edit server: %s", err.Error()) } - if edit { - if _, err = client.Guild(server.ID).Update(&disgord.UpdateGuild{ - Splash: &splash, - AFKChannelID: &afkChannel, - }); err != nil { - return diag.Errorf("Failed to edit server: %s", err.Error()) - } - // FIXME: AFKTimeout doesn't exist in UpdateGuild struct. - if _, err = client.Guild(server.ID).UpdateBuilder().SetAfkTimeout(int(afkTimeOut)).Execute(); err != nil { - return diag.Errorf("Failed to edit server: %s", err.Error()) + for _, channel := range server.Channels { + if _, err := client.ChannelDelete(channel.ID); err != nil { + return diag.Errorf("Failed to delete channel for new server: %s", err.Error()) } } // Update owner's ID if the specified one is not as same as default, // because we will receive "User is already owner" error if update to the same one. + ownerId := server.OwnerID if v, ok := d.GetOk("owner_id"); ok { - newOwnerId := disgord.ParseSnowflakeString(v.(string)) - - if server.OwnerID != newOwnerId { - if _, err = client.Guild(server.ID).Update(&disgord.UpdateGuild{ - OwnerID: &newOwnerId, - }); err != nil { - return diag.Errorf("Failed to edit server: %s", err.Error()) - } + newOwnerId := v.(string) + if ownerId != newOwnerId { + ownerId = newOwnerId } + server, err = client.GuildEdit(server.ID, &discordgo.GuildParams{ + OwnerID: ownerId, + }, discordgo.WithContext(ctx)) } - d.SetId(server.ID.String()) + d.SetId(server.ID) if _, ok := d.GetOk("owner_id"); !ok { - d.Set("owner", server.OwnerID.String()) + d.Set("owner_id", server.OwnerID) } + d.Set("region", server.Region) d.Set("icon_hash", server.Icon) d.Set("splash_hash", server.Splash) @@ -279,9 +268,9 @@ func resourceServerManagedCreate(ctx context.Context, d *schema.ResourceData, m func resourceServerRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { var diags diag.Diagnostics - client := m.(*Context).Client + client := m.(*Context).Session - server, err := client.Guild(getId(d.Id())).Get() + server, err := client.Guild(d.Id(), discordgo.WithContext(ctx)) if err != nil { return diag.Errorf("Error fetching server: %s", err.Error()) } @@ -295,101 +284,97 @@ func resourceServerRead(ctx context.Context, d *schema.ResourceData, m interface d.Set("verification_level", server.VerificationLevel) d.Set("default_message_notifications", server.DefaultMessageNotifications) d.Set("explicit_content_filter", server.ExplicitContentFilter) - if !server.AfkChannelID.IsZero() { - d.Set("afk_channel_id", server.AfkChannelID.String()) + if server.AfkChannelID != "" { + d.Set("afk_channel_id", server.AfkChannelID) } - // We don't want to set the owner to null, should only change this if its changing to something else - if d.Get("owner_id").(string) != "" && !server.OwnerID.IsZero() { - d.Set("owner_id", server.OwnerID.String()) + // We don't want to set the owner to null, should only change this if it's changing to something else + if d.Get("owner_id").(string) != "" && server.OwnerID != "" { + d.Set("owner_id", server.OwnerID) } return diags } -func toString(v interface{}) string { - return v.(string) -} - func resourceServerUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { var diags diag.Diagnostics - client := m.(*Context).Client + client := m.(*Context).Session - server, err := client.Guild(getId(d.Id())).Get() + server, err := client.Guild(d.Id(), discordgo.WithContext(ctx)) if err != nil { return diag.Errorf("Error fetching server: %s", err.Error()) } - // FIXME: Update()に書き換え - builder := client.Guild(server.ID).UpdateBuilder() + guildParams := &discordgo.GuildParams{} edit := false if d.HasChange("icon_url") { - builder.SetIcon(imgbase64.FromRemote(d.Get("icon_url").(string))) + guildParams.Icon = imgbase64.FromRemote(d.Get("icon_url").(string)) edit = true } if d.HasChange("icon_data_uri") { - builder.SetIcon(d.Get("icon_data_uri").(string)) + guildParams.Icon = d.Get("icon_data_uri").(string) edit = true } if d.HasChange("splash_url") { - builder.SetIcon(imgbase64.FromRemote(d.Get("splash_url").(string))) + guildParams.Splash = imgbase64.FromRemote(d.Get("splash_url").(string)) edit = true } if d.HasChange("splash_data_uri") { - builder.SetIcon(d.Get("splash_data_uri").(string)) + guildParams.Splash = d.Get("splash_data_uri").(string) edit = true } if d.HasChange("afk_channel_id") { - builder.SetAfkChannelID(disgord.ParseSnowflakeString(d.Get("afk_channel_id").(string))) + guildParams.AfkChannelID = d.Get("afk_channel_id").(string) edit = true } if d.HasChange("afk_timeout") { - builder.SetAfkTimeout(d.Get("afk_timeout").(int)) + guildParams.AfkTimeout = d.Get("afk_timeout").(int) edit = true } if d.HasChange("owner_id") { - builder.SetOwnerID(disgord.ParseSnowflakeString(d.Get("owner_id").(string))) + guildParams.OwnerID = d.Get("owner_id").(string) edit = true } if d.HasChange("verification_level") { - builder.SetVerificationLevel(d.Get("verification_level").(int)) + verificationLevel := discordgo.VerificationLevel(d.Get("verification_level").(int)) + guildParams.VerificationLevel = &verificationLevel edit = true } if d.HasChange("default_message_notifications") { - builder.SetDefaultMessageNotifications(disgord.DefaultMessageNotificationLvl(d.Get("default_message_notifications").(int))) + guildParams.DefaultMessageNotifications = d.Get("default_message_notifications").(int) edit = true } if d.HasChange("explicit_content_filter") { - builder.SetExplicitContentFilter(disgord.ExplicitContentFilterLvl(d.Get("explicit_content_filter").(int))) + guildParams.ExplicitContentFilter = d.Get("explicit_content_filter").(int) edit = true } if d.HasChange("name") { - builder.SetName(d.Get("name").(string)) + guildParams.Name = d.Get("name").(string) edit = true } if d.HasChange("region") { - builder.SetRegion(d.Get("region").(string)) + guildParams.Region = d.Get("region").(string) edit = true } ownerId, hasOwner := d.GetOk("owner_id") if d.HasChange("owner_id") { if hasOwner { - builder.SetOwnerID(getId(ownerId.(string))) + guildParams.OwnerID = ownerId.(string) edit = true } } else { if hasOwner { - builder.SetOwnerID(server.OwnerID) + guildParams.OwnerID = server.OwnerID edit = true } } if edit { - if _, err = builder.Execute(); err != nil { + if _, err = client.GuildEdit(server.ID, guildParams, discordgo.WithContext(ctx)); err != nil { return diag.Errorf("Failed to edit server: %s", err.Error()) } } @@ -399,9 +384,9 @@ func resourceServerUpdate(ctx context.Context, d *schema.ResourceData, m interfa func resourceServerDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { var diags diag.Diagnostics - client := m.(*Context).Client + client := m.(*Context).Session - if err := client.Guild(getId(d.Id())).Delete(); err != nil { + if err := client.GuildDelete(d.Id(), discordgo.WithContext(ctx)); err != nil { return diag.Errorf("Failed to delete server: %s", err) } diff --git a/discord/resource_discord_server_test.go b/discord/resource_discord_server_test.go new file mode 100644 index 0000000..08084ae --- /dev/null +++ b/discord/resource_discord_server_test.go @@ -0,0 +1,34 @@ +package discord + +import ( + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "testing" +) + +func TestAccResourceDiscordServer(t *testing.T) { + name := "discord_server.example" + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProviderFactories: providerFactories, + Steps: []resource.TestStep{ + { + Config: testAccResourceDiscordServer, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(name, "name", "example"), + resource.TestCheckResourceAttrSet(name, "region"), + resource.TestCheckResourceAttr(name, "default_message_notifications", "0"), + resource.TestCheckResourceAttr(name, "verification_level", "0"), + resource.TestCheckResourceAttr(name, "explicit_content_filter", "0"), + resource.TestCheckResourceAttr(name, "afk_timeout", "300"), + resource.TestCheckResourceAttrSet(name, "owner_id"), + ), + }, + }, + }) +} + +const testAccResourceDiscordServer = ` +resource "discord_server" "example" { + name = "example" +} +` diff --git a/discord/resource_discord_system_channel.go b/discord/resource_discord_system_channel.go index 14750a0..ade9bce 100644 --- a/discord/resource_discord_system_channel.go +++ b/discord/resource_discord_system_channel.go @@ -1,7 +1,7 @@ package discord import ( - "github.com/andersfylling/disgord" + "github.com/bwmarrin/discordgo" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "golang.org/x/net/context" @@ -33,76 +33,65 @@ func resourceDiscordSystemChannel() *schema.Resource { func resourceSystemChannelCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { var diags diag.Diagnostics - client := m.(*Context).Client + client := m.(*Context).Session - serverId := disgord.Snowflake(0) - if v, ok := d.GetOk("server_id"); ok { - serverId = disgord.ParseSnowflakeString(v.(string)) - } + serverId := d.Get("server_id").(string) - builder := client.Guild(serverId) - server, err := builder.Get() + server, err := client.Guild(serverId, discordgo.WithContext(ctx)) if err != nil { return diag.Errorf("Failed to find server: %s", err.Error()) } - systemChannelId := &server.SystemChannelID + systemChannelId := server.SystemChannelID if v, ok := d.GetOk("system_channel_id"); ok { - parsedId := disgord.ParseSnowflakeString(v.(string)) + systemChannelId = v.(string) - // if id is 0, system channel id cannot be set to 0, so an error has occurred. - if parsedId == disgord.Snowflake(0) { - systemChannelId = nil - } else { - systemChannelId = &parsedId - } } else { - return diag.Errorf("Failed to parse system channel id: %s", err.Error()) + return diag.Errorf("Failed to parse system channel id") } - if _, err := builder.Update(&disgord.UpdateGuild{ + if _, err := client.GuildEdit(serverId, &discordgo.GuildParams{ SystemChannelID: systemChannelId, - }); err != nil { + }, discordgo.WithContext(ctx)); err != nil { return diag.Errorf("Failed to edit server: %s", err.Error()) } - d.SetId(d.Get("server_id").(string)) + d.SetId(serverId) return diags } func resourceSystemChannelRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { var diags diag.Diagnostics - client := m.(*Context).Client + client := m.(*Context).Session - serverId := disgord.ParseSnowflakeString(d.Id()) + serverId := d.Id() - server, err := client.Guild(serverId).Get() + server, err := client.Guild(serverId, discordgo.WithContext(ctx)) if err != nil { return diag.Errorf("Error fetching server: %s", err.Error()) } - d.Set("system_channel_id", server.SystemChannelID.String()) + d.Set("system_channel_id", server.SystemChannelID) return diags } func resourceSystemChannelUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { var diags diag.Diagnostics - client := m.(*Context).Client + client := m.(*Context).Session - serverId := disgord.ParseSnowflakeString(d.Get("server_id").(string)) - builder := client.Guild(serverId) + serverId := d.Get("server_id").(string) + _, err := client.Guild(serverId, discordgo.WithContext(ctx)) - if _, err := builder.Get(); err != nil { + if err != nil { return diag.Errorf("Error fetching server: %s", err.Error()) } if d.HasChange("system_channel_id") { - id := disgord.ParseSnowflakeString(d.Get("system_channel_id").(string)) - - if _, err := builder.Update(&disgord.UpdateGuild{ - SystemChannelID: &id, - }); err != nil { + id := d.Get("system_channel_id").(string) + if _, err := client.GuildEdit(serverId, &discordgo.GuildParams{ + SystemChannelID: id, + }, discordgo.WithContext(ctx)); err != nil { return diag.Errorf("Failed to edit server: %s", err.Error()) } } @@ -112,19 +101,14 @@ func resourceSystemChannelUpdate(ctx context.Context, d *schema.ResourceData, m func resourceSystemChannelDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { var diags diag.Diagnostics - client := m.(*Context).Client + client := m.(*Context).Session - serverId := disgord.ParseSnowflakeString(d.Get("server_id").(string)) - builder := client.Guild(serverId) + serverID := d.Get("server_id").(string) - if _, err := builder.Get(); err != nil { - return diag.Errorf("Error fetching server: %s", err.Error()) - } - - if _, err := builder.Update(&disgord.UpdateGuild{ - SystemChannelID: nil, - }); err != nil { - return diag.Errorf("Failed to edit server: %s", err.Error()) + if _, err := client.GuildEdit(serverID, &discordgo.GuildParams{ + SystemChannelID: "", + }, discordgo.WithContext(ctx)); err != nil { + return diag.Errorf("Failed to edit server: %s: %s", serverID, err.Error()) } return diags diff --git a/discord/resource_discord_text_channel_test.go b/discord/resource_discord_text_channel_test.go new file mode 100644 index 0000000..80fd3af --- /dev/null +++ b/discord/resource_discord_text_channel_test.go @@ -0,0 +1,47 @@ +package discord + +import ( + "fmt" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "os" + "testing" +) + +func TestAccResourceDiscordTextChannel(t *testing.T) { + testServerID := os.Getenv("DISCORD_TEST_SERVER_ID") + if testServerID == "" { + t.Skip("DISCORD_TEST_SERVER_ID envvar must be set for acceptance tests") + } + name := "discord_text_channel.example" + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProviderFactories: providerFactories, + Steps: []resource.TestStep{ + { + Config: testAccResourceDiscordTextChannel(testServerID), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(name, "server_id", testServerID), + resource.TestCheckResourceAttr(name, "name", "terraform-text-channel"), + resource.TestCheckResourceAttr(name, "type", "text"), + resource.TestCheckResourceAttr(name, "position", "1"), + resource.TestCheckResourceAttrSet(name, "channel_id"), + resource.TestCheckResourceAttr(name, "topic", "Testing text channel"), + resource.TestCheckResourceAttr(name, "nsfw", "false"), + resource.TestCheckResourceAttr(name, "sync_perms_with_category", "false"), + ), + }, + }, + }) +} + +func testAccResourceDiscordTextChannel(serverID string) string { + return fmt.Sprintf(` + resource "discord_text_channel" "example" { + server_id = "%[1]s" + name = "terraform-text-channel" + position = 1 + topic = "Testing text channel" + nsfw = false + sync_perms_with_category = false + }`, serverID) +} diff --git a/discord/resource_discord_voice_channel_test.go b/discord/resource_discord_voice_channel_test.go new file mode 100644 index 0000000..baf0cea --- /dev/null +++ b/discord/resource_discord_voice_channel_test.go @@ -0,0 +1,47 @@ +package discord + +import ( + "fmt" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "os" + "testing" +) + +func TestAccResourceDiscordVoiceChannel(t *testing.T) { + testServerID := os.Getenv("DISCORD_TEST_SERVER_ID") + if testServerID == "" { + t.Skip("DISCORD_TEST_SERVER_ID envvar must be set for acceptance tests") + } + name := "discord_voice_channel.example" + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProviderFactories: providerFactories, + Steps: []resource.TestStep{ + { + Config: testAccResourceDiscordVoiceChannel(testServerID), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(name, "server_id", testServerID), + resource.TestCheckResourceAttr(name, "name", "terraform-voice-channel"), + resource.TestCheckResourceAttr(name, "type", "voice"), + resource.TestCheckResourceAttr(name, "position", "1"), + resource.TestCheckResourceAttr(name, "bitrate", "64000"), + resource.TestCheckResourceAttr(name, "user_limit", "4"), + resource.TestCheckResourceAttr(name, "sync_perms_with_category", "false"), + resource.TestCheckResourceAttrSet(name, "channel_id"), + ), + }, + }, + }) +} + +func testAccResourceDiscordVoiceChannel(serverID string) string { + return fmt.Sprintf(` + resource "discord_voice_channel" "example" { + server_id = "%[1]s" + name = "terraform-voice-channel" + position = 1 + bitrate = 64000 + user_limit = 4 + sync_perms_with_category = false + }`, serverID) +} diff --git a/discord/resource_discord_webhook.go b/discord/resource_discord_webhook.go index 86762c9..32ef37e 100644 --- a/discord/resource_discord_webhook.go +++ b/discord/resource_discord_webhook.go @@ -1,7 +1,7 @@ package discord import ( - "github.com/andersfylling/disgord" + "github.com/bwmarrin/discordgo" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/polds/imgbase64" @@ -67,9 +67,9 @@ func resourceDiscordWebhook() *schema.Resource { func resourceWebhookCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { var diags diag.Diagnostics - client := m.(*Context).Client + client := m.(*Context).Session - channelId := getId(d.Get("channel_id").(string)) + channelId := d.Get("channel_id").(string) avatar := "" if v, ok := d.GetOk("avatar_url"); ok { @@ -79,15 +79,12 @@ func resourceWebhookCreate(ctx context.Context, d *schema.ResourceData, m interf avatar = v.(string) } - if webhook, err := client.Channel(channelId).CreateWebhook(&disgord.CreateWebhook{ - Name: d.Get("name").(string), - Avatar: avatar, - }); err != nil { + if webhook, err := client.WebhookCreate(channelId, d.Get("name").(string), avatar, discordgo.WithContext(ctx)); err != nil { return diag.Errorf("Failed to create webhook: %s", err.Error()) } else { - url := "https://discord.com/api/webhooks/" + webhook.ID.String() + "/" + webhook.Token + url := "https://discord.com/api/webhooks/" + webhook.ID + "/" + webhook.Token - d.SetId(webhook.ID.String()) + d.SetId(webhook.ID) d.Set("avatar_hash", webhook.Avatar) d.Set("token", webhook.Token) d.Set("url", url) @@ -100,14 +97,14 @@ func resourceWebhookCreate(ctx context.Context, d *schema.ResourceData, m interf func resourceWebhookRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { var diags diag.Diagnostics - client := m.(*Context).Client + client := m.(*Context).Session - if webhook, err := client.Webhook(getId(d.Id())).Get(); err != nil { + if webhook, err := client.Webhook(d.Id(), discordgo.WithContext(ctx)); err != nil { d.SetId("") } else { - url := "https://discord.com/api/webhooks/" + webhook.ID.String() + "/" + webhook.Token + url := "https://discord.com/api/webhooks/" + webhook.ID + "/" + webhook.Token - d.Set("channel_id", webhook.ChannelID.String()) + d.Set("channel_id", webhook.ChannelID) d.Set("name", webhook.Name) d.Set("avatar_hash", webhook.Avatar) d.Set("token", webhook.Token) @@ -121,9 +118,9 @@ func resourceWebhookRead(ctx context.Context, d *schema.ResourceData, m interfac func resourceWebhookUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { var diags diag.Diagnostics - client := m.(*Context).Client + client := m.(*Context).Session - channelId := getId(d.Get("channel_id").(string)) + channelId := d.Get("channel_id").(string) name := d.Get("name").(string) avatar := "" @@ -134,16 +131,11 @@ func resourceWebhookUpdate(ctx context.Context, d *schema.ResourceData, m interf avatar = v.(string) } - if webhook, err := client.Webhook(getId(d.Id())).Update(&disgord.UpdateWebhook{ - ChannelID: &channelId, - Name: &name, - Avatar: &avatar, - }); err != nil { + if webhook, err := client.WebhookEdit(d.Id(), name, avatar, channelId, discordgo.WithContext(ctx)); err != nil { return diag.Errorf("Failed to update webhook %s: %s", d.Id(), err.Error()) } else { - url := "https://discord.com/api/webhooks/" + webhook.ID.String() + "/" + webhook.Token - - d.Set("channel_id", webhook.ChannelID.String()) + url := "https://discord.com/api/webhooks/" + webhook.ID + "/" + webhook.Token + d.Set("channel_id", webhook.ChannelID) d.Set("name", webhook.Name) d.Set("avatar_hash", webhook.Avatar) d.Set("token", webhook.Token) @@ -157,9 +149,9 @@ func resourceWebhookUpdate(ctx context.Context, d *schema.ResourceData, m interf func resourceWebhookDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { var diags diag.Diagnostics - client := m.(*Context).Client + client := m.(*Context).Session - if err := client.Webhook(getId(d.Id())).Delete(); err != nil { + if err := client.WebhookDelete(d.Id(), discordgo.WithContext(ctx)); err != nil { return diag.FromErr(err) } else { return diags diff --git a/discord/resource_discord_webhook_test.go b/discord/resource_discord_webhook_test.go new file mode 100644 index 0000000..d54aef0 --- /dev/null +++ b/discord/resource_discord_webhook_test.go @@ -0,0 +1,43 @@ +package discord + +import ( + "fmt" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "os" + "testing" +) + +func TestAccResourceDiscordWebhook(t *testing.T) { + testChannelID := os.Getenv("DISCORD_TEST_CHANNEL_ID") + if testChannelID == "" { + t.Skip("DISCORD_TEST_CHANNEL_ID envvar must be set for acceptance tests") + } + name := "discord_webhook.example" + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProviderFactories: providerFactories, + Steps: []resource.TestStep{ + { + Config: testAccResourceDiscordWebhook(testChannelID), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(name, "channel_id", testChannelID), + resource.TestCheckResourceAttr(name, "name", "terraform-test"), + resource.TestCheckResourceAttr(name, "avatar_url", "https://www.terraform.io/assets/images/og-image-8b3e4f7d.png"), + resource.TestCheckResourceAttrSet(name, "token"), + resource.TestCheckResourceAttrSet(name, "url"), + resource.TestCheckResourceAttrSet(name, "slack_url"), + resource.TestCheckResourceAttrSet(name, "github_url"), + ), + }, + }, + }) +} + +func testAccResourceDiscordWebhook(channelID string) string { + return fmt.Sprintf(` + resource "discord_webhook" "example" { + channel_id = "%[1]s" + name = "terraform-test" + avatar_url = "https://www.terraform.io/assets/images/og-image-8b3e4f7d.png" + }`, channelID) +} diff --git a/discord/util.go b/discord/util.go index d3fee0d..fd514c0 100644 --- a/discord/util.go +++ b/discord/util.go @@ -23,3 +23,42 @@ func contains[T comparable](array []T, value T) bool { return false } + +// BoolPtr is a helper routine that allocates a new bool value to store v and +// returns a pointer to it. +func BoolPtr(v bool) *bool { return &v } + +// Bool is a helper routine that accepts a bool pointer and returns a value +// to it. +func Bool(v *bool) bool { + if v != nil { + return *v + } + return false +} + +// IntPtr is a helper routine that allocates a new int value to store v and +// returns a pointer to it. +func IntPtr(v int) *int { return &v } + +// Int is a helper routine that accepts a int pointer and returns a value +// to it. +func Int(v *int) int { + if v != nil { + return *v + } + return 0 +} + +// Int64 is a helper routine that accepts an int64 pointer and returns a +// value to it. +func Int64(v *int64) int64 { + if v != nil { + return *v + } + return 0 +} + +// Int64Ptr is a helper routine that allocates a new int64 value to store v +// and returns a pointer to it. +func Int64Ptr(v int64) *int64 { return &v } diff --git a/discord/util_channel.go b/discord/util_channel.go index 76951a2..7e7e997 100644 --- a/discord/util_channel.go +++ b/discord/util_channel.go @@ -3,11 +3,10 @@ package discord import ( "context" - "github.com/andersfylling/disgord" "github.com/bwmarrin/discordgo" ) -func getTextChannelType(channelType disgord.ChannelType) (string, bool) { +func getTextChannelType(channelType discordgo.ChannelType) (string, bool) { switch channelType { case 0: return "text", true @@ -24,18 +23,18 @@ func getTextChannelType(channelType disgord.ChannelType) (string, bool) { return "text", false } -func getDiscordChannelType(name string) (disgord.ChannelType, bool) { +func getDiscordChannelType(name string) (discordgo.ChannelType, bool) { switch name { case "text": - return 0, true + return discordgo.ChannelTypeGuildText, true case "voice": - return 2, true + return discordgo.ChannelTypeGuildVoice, true case "category": - return 4, true + return discordgo.ChannelTypeGuildCategory, true case "news": - return 5, true + return discordgo.ChannelTypeGuildNews, true case "store": - return 6, true + return discordgo.ChannelTypeGuildStore, true } return 0, false @@ -47,7 +46,7 @@ type Channel struct { Channel *discordgo.Channel } -func findChannelById(array []*disgord.Channel, id disgord.Snowflake) *disgord.Channel { +func findChannelById(array []*discordgo.Channel, id string) *discordgo.Channel { for _, element := range array { if element.ID == id { return element @@ -57,7 +56,7 @@ func findChannelById(array []*disgord.Channel, id disgord.Snowflake) *disgord.Ch return nil } -func arePermissionsSynced(from *disgord.Channel, to *disgord.Channel) bool { +func arePermissionsSynced(from *discordgo.Channel, to *discordgo.Channel) bool { for _, p1 := range from.PermissionOverwrites { cont := false for _, p2 := range to.PermissionOverwrites { @@ -87,20 +86,15 @@ func arePermissionsSynced(from *disgord.Channel, to *disgord.Channel) bool { return true } -func syncChannelPermissions(c *disgord.Client, ctx context.Context, from *disgord.Channel, to *disgord.Channel) error { +func syncChannelPermissions(c *discordgo.Session, ctx context.Context, from *discordgo.Channel, to *discordgo.Channel) error { for _, p := range to.PermissionOverwrites { - if err := c.Channel(to.ID).DeletePermission(p.ID); err != nil { + if err := c.ChannelPermissionDelete(to.ID, p.ID); err != nil { return err } } for _, p := range from.PermissionOverwrites { - params := &disgord.UpdateChannelPermissions{ - Allow: p.Allow, - Deny: p.Deny, - Type: uint(p.Type), - } - if err := c.Channel(to.ID).UpdatePermissions(p.ID, params); err != nil { + if err := c.ChannelPermissionSet(to.ID, p.ID, discordgo.PermissionOverwriteTypeRole, p.Allow, p.Deny, discordgo.WithContext(ctx)); err != nil { return err } } @@ -108,12 +102,12 @@ func syncChannelPermissions(c *disgord.Client, ctx context.Context, from *disgor return nil } -func getDiscordChannelPermissionType(value string) (uint, bool) { +func getDiscordChannelPermissionType(value string) (discordgo.PermissionOverwriteType, bool) { switch value { case "role": - return 0, true + return discordgo.PermissionOverwriteTypeRole, true case "user": - return 1, true + return discordgo.PermissionOverwriteTypeMember, true default: return 0, false } diff --git a/discord/util_channel_test.go b/discord/util_channel_test.go index 59d27eb..fd2026e 100644 --- a/discord/util_channel_test.go +++ b/discord/util_channel_test.go @@ -1,9 +1,8 @@ package discord import ( + "github.com/bwmarrin/discordgo" "testing" - - "github.com/andersfylling/disgord" ) func TestGetTextChannelType(t *testing.T) { @@ -24,7 +23,7 @@ func TestGetTextChannelType(t *testing.T) { } for _, p := range params { - chType := disgord.ChannelType(p.id) + chType := discordgo.ChannelType(p.id) resChType, resIsHit := getTextChannelType(chType) if p.chType != resChType { t.Errorf("id: %v - chType Error: ex: %v, ac: %v", p.id, p.chType, resChType) diff --git a/discord/util_embed.go b/discord/util_embed.go index 126ad62..d97d19f 100644 --- a/discord/util_embed.go +++ b/discord/util_embed.go @@ -2,48 +2,38 @@ package discord import ( "encoding/json" - "time" - - "github.com/andersfylling/disgord" + "github.com/bwmarrin/discordgo" ) type UnmappedEmbed struct { - Title string `json:"title,omitempty"` // title of embed - Description string `json:"description,omitempty"` // description of embed - URL string `json:"url,omitempty"` // url of embed - Timestamp string `json:"timestamp,omitempty"` // timestamp timestamp of embed content - Color int `json:"color,omitempty"` // color code of the embed - Footer []*disgord.EmbedFooter `json:"footer,omitempty"` // embed footer object footer information - Image []*disgord.EmbedImage `json:"image,omitempty"` // embed image object image information - Thumbnail []*disgord.EmbedThumbnail `json:"thumbnail,omitempty"` // embed thumbnail object thumbnail information - Video []*disgord.EmbedVideo `json:"video,omitempty"` // embed video object video information - Provider []*disgord.EmbedProvider `json:"provider,omitempty"` // embed provider object provider information - Author []*disgord.EmbedAuthor `json:"author,omitempty"` // embed author object author information - Fields []*disgord.EmbedField `json:"fields,omitempty"` // array of embed field objects fields information + Title string `json:"title,omitempty"` // title of embed + Description string `json:"description,omitempty"` // description of embed + URL string `json:"url,omitempty"` // url of embed + Timestamp string `json:"timestamp,omitempty"` // timestamp timestamp of embed content + Color int `json:"color,omitempty"` // color code of the embed + Footer []*discordgo.MessageEmbedFooter `json:"footer,omitempty"` // embed footer object footer information + Image []*discordgo.MessageEmbedImage `json:"image,omitempty"` // embed image object image information + Thumbnail []*discordgo.MessageEmbedThumbnail `json:"thumbnail,omitempty"` // embed thumbnail object thumbnail information + Video []*discordgo.MessageEmbedVideo `json:"video,omitempty"` // embed video object video information + Provider []*discordgo.MessageEmbedProvider `json:"provider,omitempty"` // embed provider object provider information + Author []*discordgo.MessageEmbedAuthor `json:"author,omitempty"` // embed author object author information + Fields []*discordgo.MessageEmbedField `json:"fields,omitempty"` // array of embed field objects fields information } -func buildEmbed(embedList []interface{}) (*disgord.Embed, error) { +func buildEmbed(embedList []interface{}) (*discordgo.MessageEmbed, error) { embedMap := embedList[0].(map[string]interface{}) - var time disgord.Time - if embedMap["timestamp"].(string) != "" { - err := time.UnmarshalText([]byte(embedMap["timestamp"].(string))) - if err != nil { - return nil, err - } - } - - embed := &disgord.Embed{ + embed := &discordgo.MessageEmbed{ Title: embedMap["title"].(string), Description: embedMap["description"].(string), URL: embedMap["url"].(string), Color: embedMap["color"].(int), - Timestamp: time, + Timestamp: embedMap["timestamp"].(string), } if len(embedMap["footer"].([]interface{})) > 0 { footerMap := embedMap["footer"].([]interface{})[0].(map[string]interface{}) - embed.Footer = &disgord.EmbedFooter{ + embed.Footer = &discordgo.MessageEmbedFooter{ Text: footerMap["text"].(string), IconURL: footerMap["icon_url"].(string), } @@ -51,7 +41,7 @@ func buildEmbed(embedList []interface{}) (*disgord.Embed, error) { if len(embedMap["image"].([]interface{})) > 0 { imageMap := embedMap["image"].([]interface{})[0].(map[string]interface{}) - embed.Image = &disgord.EmbedImage{ + embed.Image = &discordgo.MessageEmbedImage{ URL: imageMap["url"].(string), Width: imageMap["width"].(int), Height: imageMap["height"].(int), @@ -60,7 +50,7 @@ func buildEmbed(embedList []interface{}) (*disgord.Embed, error) { if len(embedMap["thumbnail"].([]interface{})) > 0 { thumbnailMap := embedMap["thumbnail"].([]interface{})[0].(map[string]interface{}) - embed.Thumbnail = &disgord.EmbedThumbnail{ + embed.Thumbnail = &discordgo.MessageEmbedThumbnail{ URL: thumbnailMap["url"].(string), Width: thumbnailMap["width"].(int), Height: thumbnailMap["height"].(int), @@ -69,7 +59,7 @@ func buildEmbed(embedList []interface{}) (*disgord.Embed, error) { if len(embedMap["video"].([]interface{})) > 0 { videoMap := embedMap["video"].([]interface{})[0].(map[string]interface{}) - embed.Video = &disgord.EmbedVideo{ + embed.Video = &discordgo.MessageEmbedVideo{ URL: videoMap["url"].(string), Width: videoMap["width"].(int), Height: videoMap["height"].(int), @@ -78,7 +68,7 @@ func buildEmbed(embedList []interface{}) (*disgord.Embed, error) { if len(embedMap["provider"].([]interface{})) > 0 { providerMap := embedMap["provider"].([]interface{})[0].(map[string]interface{}) - embed.Provider = &disgord.EmbedProvider{ + embed.Provider = &discordgo.MessageEmbedProvider{ URL: providerMap["url"].(string), Name: providerMap["name"].(string), } @@ -86,7 +76,7 @@ func buildEmbed(embedList []interface{}) (*disgord.Embed, error) { if len(embedMap["author"].([]interface{})) > 0 { authorMap := embedMap["author"].([]interface{})[0].(map[string]interface{}) - embed.Author = &disgord.EmbedAuthor{ + embed.Author = &discordgo.MessageEmbedAuthor{ Name: authorMap["name"].(string), URL: authorMap["url"].(string), IconURL: authorMap["icon_url"].(string), @@ -96,7 +86,7 @@ func buildEmbed(embedList []interface{}) (*disgord.Embed, error) { for _, field := range embedMap["fields"].([]interface{}) { fieldMap := field.(map[string]interface{}) - embed.Fields = append(embed.Fields, &disgord.EmbedField{ + embed.Fields = append(embed.Fields, &discordgo.MessageEmbedField{ Name: fieldMap["name"].(string), Value: fieldMap["value"].(string), Inline: fieldMap["inline"].(bool), @@ -106,40 +96,35 @@ func buildEmbed(embedList []interface{}) (*disgord.Embed, error) { return embed, nil } -func unbuildEmbed(embed *disgord.Embed) []interface{} { +func unbuildEmbed(embed *discordgo.MessageEmbed) []interface{} { var ret interface{} - var timestamp string - if !embed.Timestamp.IsZero() { - timestamp = embed.Timestamp.Format(time.RFC3339) - } - e := &UnmappedEmbed{ Title: embed.Title, Description: embed.Description, URL: embed.URL, - Timestamp: timestamp, + Timestamp: embed.Timestamp, Color: embed.Color, Fields: embed.Fields, } if embed.Footer != nil { - e.Footer = []*disgord.EmbedFooter{embed.Footer} + e.Footer = []*discordgo.MessageEmbedFooter{embed.Footer} } if embed.Image != nil { - e.Image = []*disgord.EmbedImage{embed.Image} + e.Image = []*discordgo.MessageEmbedImage{embed.Image} } if embed.Thumbnail != nil { - e.Thumbnail = []*disgord.EmbedThumbnail{embed.Thumbnail} + e.Thumbnail = []*discordgo.MessageEmbedThumbnail{embed.Thumbnail} } if embed.Video != nil { - e.Video = []*disgord.EmbedVideo{embed.Video} + e.Video = []*discordgo.MessageEmbedVideo{embed.Video} } if embed.Provider != nil { - e.Provider = []*disgord.EmbedProvider{embed.Provider} + e.Provider = []*discordgo.MessageEmbedProvider{embed.Provider} } if embed.Author != nil { - e.Author = []*disgord.EmbedAuthor{embed.Author} + e.Author = []*discordgo.MessageEmbedAuthor{embed.Author} } j, _ := json.MarshalIndent(e, "", " ") diff --git a/discord/util_general.go b/discord/util_general.go index be2a165..4f076f0 100644 --- a/discord/util_general.go +++ b/discord/util_general.go @@ -3,8 +3,6 @@ package discord import ( "fmt" "strings" - - "github.com/andersfylling/disgord" ) func parseTwoIds(id string) (string, string, error) { @@ -35,38 +33,3 @@ func parseThreeIds(id string) (string, string, string, error) { func generateThreePartId(one string, two string, three string) string { return fmt.Sprintf("%s:%s:%s", one, two, three) } - -func getId(v string) disgord.Snowflake { - return disgord.ParseSnowflakeString(v) -} - -func getMinorId(v interface{}) disgord.Snowflake { - str := v.(string) - if strings.Contains(str, ":") { - _, secondId, _ := parseTwoIds(str) - - return getId(secondId) - } - - return getId(v.(string)) -} - -func getMajorId(v interface{}) disgord.Snowflake { - str := v.(string) - if strings.Contains(str, ":") { - firstId, _, _ := parseTwoIds(str) - - return getId(firstId) - } - - return getId(v.(string)) -} - -func getBothIds(v interface{}) (disgord.Snowflake, disgord.Snowflake, error) { - firstId, secondId, err := parseTwoIds(v.(string)) - if err != nil { - return 0, 0, err - } - - return disgord.ParseSnowflakeString(firstId), disgord.ParseSnowflakeString(secondId), nil -} diff --git a/discord/util_member.go b/discord/util_member.go index c5479aa..65239e1 100644 --- a/discord/util_member.go +++ b/discord/util_member.go @@ -1,10 +1,12 @@ package discord -import "github.com/andersfylling/disgord" +import ( + "github.com/bwmarrin/discordgo" +) -func hasRole(member *disgord.Member, roleId disgord.Snowflake) bool { +func hasRole(member *discordgo.Member, roleId string) bool { for _, r := range member.Roles { - if r.String() == roleId.String() { + if r == roleId { return true } } diff --git a/discord/util_role.go b/discord/util_role.go index 8217083..68c29ce 100644 --- a/discord/util_role.go +++ b/discord/util_role.go @@ -3,26 +3,26 @@ package discord import ( "context" - "github.com/andersfylling/disgord" + "github.com/bwmarrin/discordgo" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" ) type Role struct { - ServerId disgord.Snowflake - RoleId disgord.Snowflake - Role *disgord.Role + ServerId string + RoleId string + Role *discordgo.Role } -func insertRole(array []*disgord.Role, value *disgord.Role, index int) []*disgord.Role { - return append(array[:index], append([]*disgord.Role{value}, array[index:]...)...) +func insertRole(array []*discordgo.Role, value *discordgo.Role, index int) []*discordgo.Role { + return append(array[:index], append([]*discordgo.Role{value}, array[index:]...)...) } -func removeRole(array []*disgord.Role, index int) []*disgord.Role { +func removeRole(array []*discordgo.Role, index int) []*discordgo.Role { return append(array[:index], array[index+1:]...) } -func removeRoleById(array []disgord.Snowflake, id disgord.Snowflake) []disgord.Snowflake { - roles := make([]disgord.Snowflake, 0, len(array)) +func removeRoleById(array []string, id string) []string { + roles := make([]string, 0, len(array)) for _, x := range array { if x != id { roles = append(roles, x) @@ -32,12 +32,12 @@ func removeRoleById(array []disgord.Snowflake, id disgord.Snowflake) []disgord.S return roles } -func moveRole(array []*disgord.Role, srcIndex int, dstIndex int) []*disgord.Role { +func moveRole(array []*discordgo.Role, srcIndex int, dstIndex int) []*discordgo.Role { value := array[srcIndex] return insertRole(removeRole(array, srcIndex), value, dstIndex) } -func findRoleIndex(array []*disgord.Role, value *disgord.Role) (int, bool) { +func findRoleIndex(array []*discordgo.Role, value *discordgo.Role) (int, bool) { for index, element := range array { if element.ID == value.ID { return index, true @@ -47,7 +47,7 @@ func findRoleIndex(array []*disgord.Role, value *disgord.Role) (int, bool) { return -1, false } -func findRoleById(array []*disgord.Role, id disgord.Snowflake) *disgord.Role { +func findRoleById(array []*discordgo.Role, id string) *discordgo.Role { for _, element := range array { if element.ID == id { return element @@ -57,10 +57,10 @@ func findRoleById(array []*disgord.Role, id disgord.Snowflake) *disgord.Role { return nil } -func reorderRoles(ctx context.Context, m interface{}, serverId disgord.Snowflake, role *disgord.Role, position int) (bool, diag.Diagnostics) { - client := m.(*Context).Client +func reorderRoles(ctx context.Context, m interface{}, serverId string, role *discordgo.Role, position int) (bool, diag.Diagnostics) { + client := m.(*Context).Session - roles, err := client.Guild(serverId).GetRoles() + roles, err := client.GuildRoles(serverId, discordgo.WithContext(ctx)) if err != nil { return false, diag.Errorf("Failed to fetch roles: %s", err.Error()) } @@ -71,23 +71,17 @@ func reorderRoles(ctx context.Context, m interface{}, serverId disgord.Snowflake moveRole(roles, index, position) - params := make([]disgord.UpdateGuildRolePositions, 0, len(roles)) - for index, r := range roles { - params = append(params, disgord.UpdateGuildRolePositions{ID: r.ID, Position: index}) - } - - if roles, err = client.Guild(serverId).UpdateRolePositions(params); err != nil { + if roles, err = client.GuildRoleReorder(serverId, roles, discordgo.WithContext(ctx)); err != nil { return false, diag.Errorf("Failed to re-order roles: %s", err.Error()) } return true, nil } -func getRole(ctx context.Context, client *disgord.Client, serverId disgord.Snowflake, roleId disgord.Snowflake) (*disgord.Role, error) { - if roles, err := client.Guild(serverId).GetRoles(); err != nil { +func getRole(ctx context.Context, client *discordgo.Session, serverId string, roleId string) (*discordgo.Role, error) { + if roles, err := client.GuildRoles(serverId, discordgo.WithContext(ctx)); err != nil { return nil, err } else { - role := findRoleById(roles, roleId) - return role, nil + return findRoleById(roles, roleId), nil } } diff --git a/go.mod b/go.mod index dde57cd..88a2f22 100644 --- a/go.mod +++ b/go.mod @@ -5,8 +5,6 @@ go 1.21 toolchain go1.22.2 require ( - github.com/andersfylling/disgord v0.35.1 - github.com/andersfylling/snowflake/v5 v5.0.1 github.com/bwmarrin/discordgo v0.28.1 github.com/hashicorp/go-cty v1.4.1-0.20200723130312-85980079f637 github.com/hashicorp/terraform-plugin-sdk/v2 v2.33.0 @@ -16,24 +14,32 @@ require ( ) require ( + github.com/ProtonMail/go-crypto v1.1.0-alpha.2-proton // indirect github.com/agext/levenshtein v1.2.3 // indirect github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect + github.com/cloudflare/circl v1.3.8 // indirect github.com/fatih/color v1.16.0 // indirect - github.com/golang/protobuf v1.5.3 // indirect + github.com/golang/protobuf v1.5.4 // indirect github.com/google/go-cmp v0.6.0 // indirect - github.com/gorilla/websocket v1.5.0 // indirect - github.com/hashicorp/go-hclog v1.5.0 // indirect + github.com/gorilla/websocket v1.5.1 // indirect + github.com/hashicorp/errwrap v1.1.0 // indirect + github.com/hashicorp/go-checkpoint v0.5.0 // indirect + github.com/hashicorp/go-cleanhttp v0.5.2 // indirect + github.com/hashicorp/go-hclog v1.6.3 // indirect + github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/go-plugin v1.6.0 // indirect github.com/hashicorp/go-uuid v1.0.3 // indirect github.com/hashicorp/go-version v1.6.0 // indirect - github.com/hashicorp/hcl/v2 v2.19.1 // indirect + github.com/hashicorp/hc-install v0.6.4 // indirect + github.com/hashicorp/hcl/v2 v2.20.1 // indirect github.com/hashicorp/logutils v1.0.0 // indirect - github.com/hashicorp/terraform-plugin-go v0.22.0 // indirect + github.com/hashicorp/terraform-exec v0.20.0 // indirect + github.com/hashicorp/terraform-json v0.21.0 // indirect + github.com/hashicorp/terraform-plugin-go v0.22.2 // indirect github.com/hashicorp/terraform-plugin-log v0.9.0 // indirect github.com/hashicorp/terraform-registry-address v0.2.3 // indirect github.com/hashicorp/terraform-svchost v0.1.1 // indirect github.com/hashicorp/yamux v0.1.1 // indirect - github.com/klauspost/compress v1.15.12 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect @@ -42,21 +48,20 @@ require ( github.com/mitchellh/go-wordwrap v1.0.1 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect - github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect - github.com/modern-go/reflect2 v1.0.2 // indirect github.com/oklog/run v1.1.0 // indirect github.com/vmihailenco/msgpack v4.0.4+incompatible // indirect github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect - github.com/zclconf/go-cty v1.14.2 // indirect - go.uber.org/atomic v1.10.0 // indirect + github.com/zclconf/go-cty v1.14.4 // indirect golang.org/x/crypto v0.22.0 // indirect + golang.org/x/mod v0.17.0 // indirect + golang.org/x/sync v0.7.0 // indirect golang.org/x/sys v0.19.0 // indirect golang.org/x/text v0.14.0 // indirect + golang.org/x/tools v0.20.0 // indirect google.golang.org/appengine v1.6.8 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20231106174013-bbf56f31fb17 // indirect - google.golang.org/grpc v1.61.1 // indirect - google.golang.org/protobuf v1.32.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240415180920-8c6c420018be // indirect + google.golang.org/grpc v1.63.2 // indirect + google.golang.org/protobuf v1.33.0 // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect - nhooyr.io/websocket v1.8.7 // indirect ) diff --git a/go.sum b/go.sum index e26787b..46ca8de 100644 --- a/go.sum +++ b/go.sum @@ -1,9 +1,11 @@ +dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= +dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= +github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= +github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= +github.com/ProtonMail/go-crypto v1.1.0-alpha.2-proton h1:HKz85FwoXx86kVtTvFke7rgHvq/HoloSUvW5semjFWs= +github.com/ProtonMail/go-crypto v1.1.0-alpha.2-proton/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE= github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7lmo= github.com/agext/levenshtein v1.2.3/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= -github.com/andersfylling/disgord v0.35.1 h1:auhxW9z96/uSF7MYwfuv8AP71AVIc0+jZQWjZdwIqNE= -github.com/andersfylling/disgord v0.35.1/go.mod h1:gTzujw2mWxJWxAPo3LwxG5+a4/n4ikdD+JMb1mONmUM= -github.com/andersfylling/snowflake/v5 v5.0.1 h1:unXbYSij6tRCGJzoLz9zl3nJsqd9hu7bbYSgB8K8/i0= -github.com/andersfylling/snowflake/v5 v5.0.1/go.mod h1:AdhrB+kewjnQInv8cR7ABe2SGoVXh79njnipUnz1HFc= github.com/apparentlymart/go-textseg/v12 v12.0.0/go.mod h1:S/4uRK2UtaQttw1GenVJEynmyUenKwP++x/+DdGV/Ec= github.com/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew1u1fNQOlOtuGxQY= github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4= @@ -11,67 +13,74 @@ github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZ github.com/bufbuild/protocompile v0.4.0/go.mod h1:3v93+mbWn/v3xzN+31nwkJfrEpAUwp+BagBSZWx+TP8= github.com/bwmarrin/discordgo v0.28.1 h1:gXsuo2GBO7NbR6uqmrrBDplPUx2T3nzu775q/Rd1aG4= github.com/bwmarrin/discordgo v0.28.1/go.mod h1:NJZpH+1AfhIcyQsPeuBKsUtYrRnjkyu0kIVMCHkZtRY= +github.com/cloudflare/circl v1.3.8 h1:j+V8jJt09PoeMFIu2uh5JUyEaIHTXVOHslFoLNAKqwI= +github.com/cloudflare/circl v1.3.8/go.mod h1:PDRU+oXvdD7KCtgKxW95M5Z8BpSCJXQORiZFnBQS5QU= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= +github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= +github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= -github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= -github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= -github.com/gin-gonic/gin v1.6.3 h1:ahKqKTFpO5KTPHxWZjEdPScmYaGtLo8Y4DMHoEsnp14= -github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= -github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= -github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= -github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= -github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= -github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no= -github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= -github.com/go-playground/validator/v10 v10.2.0 h1:KgJ0snyC2R9VXYN2rneOtQcw5aHQB1Vv0sFl1UcHBOY= -github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= +github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= +github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= +github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+mTU= +github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow= +github.com/go-git/go-git/v5 v5.12.0 h1:7Md+ndsjrzZxbddRDZjF14qK+NN56sy6wkqaVrjZtys= +github.com/go-git/go-git/v5 v5.12.0/go.mod h1:FTM9VKtnI2m65hNI/TenDDDnUf2Q9FHnXYjuz9i5OEY= github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68= github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= -github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee h1:s+21KNqlpePfkah2I+gwHF8xmJWRjooY+5248k6m4A0= -github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= -github.com/gobwas/pool v0.2.0 h1:QEmUOlnSjWtnpRGHF3SauEiOsy82Cup83Vf2LcMlnc8= -github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= -github.com/gobwas/ws v1.0.2 h1:CoAavW/wd/kulfZmSIBt6p24n4j7tHgNVCjsfHVNUbo= -github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= 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/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= +github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= +github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-checkpoint v0.5.0 h1:MFYpPZCnQqQTE18jFwSII6eUQrD/oxMFp3mlgcqk5mU= +github.com/hashicorp/go-checkpoint v0.5.0/go.mod h1:7nfLNL10NsxqO4iWuW6tWW0HjZuDrwkBuEQsVcpCOgg= +github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= +github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= github.com/hashicorp/go-cty v1.4.1-0.20200723130312-85980079f637 h1:Ud/6/AdmJ1R7ibdS0Wo5MWPj0T1R0fkpaD087bBaW8I= github.com/hashicorp/go-cty v1.4.1-0.20200723130312-85980079f637/go.mod h1:EiZBMaudVLy8fmjf9Npq1dq9RalhveqZG5w/yz3mHWs= -github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c= -github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= +github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k= +github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= +github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= +github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/hashicorp/go-plugin v1.6.0 h1:wgd4KxHJTVGGqWBq4QPB1i5BZNEx9BR8+OFmHDmTk8A= github.com/hashicorp/go-plugin v1.6.0/go.mod h1:lBS5MtSSBZk0SHc66KACcjjlU6WzEVP/8pwz68aMkCI= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/hashicorp/hcl/v2 v2.19.1 h1://i05Jqznmb2EXqa39Nsvyan2o5XyMowW5fnCKW5RPI= -github.com/hashicorp/hcl/v2 v2.19.1/go.mod h1:ThLC89FV4p9MPW804KVbe/cEXoQ8NZEh+JtMeeGErHE= +github.com/hashicorp/hc-install v0.6.4 h1:QLqlM56/+SIIGvGcfFiwMY3z5WGXT066suo/v9Km8e0= +github.com/hashicorp/hc-install v0.6.4/go.mod h1:05LWLy8TD842OtgcfBbOT0WMoInBMUSHjmDx10zuBIA= +github.com/hashicorp/hcl/v2 v2.20.1 h1:M6hgdyz7HYt1UN9e61j+qKJBqR3orTWbI1HKBJEdxtc= +github.com/hashicorp/hcl/v2 v2.20.1/go.mod h1:TZDqQ4kNKCbh1iJp99FdPiUaVDDUPivbqxZulxDYqL4= github.com/hashicorp/logutils v1.0.0 h1:dLEQVugN8vlakKOUE3ihGLTZJRB4j+M2cdTm/ORI65Y= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= -github.com/hashicorp/terraform-plugin-go v0.22.0 h1:1OS1Jk5mO0f5hrziWJGXXIxBrMe2j/B8E+DVGw43Xmc= -github.com/hashicorp/terraform-plugin-go v0.22.0/go.mod h1:mPULV91VKss7sik6KFEcEu7HuTogMLLO/EvWCuFkRVE= +github.com/hashicorp/terraform-exec v0.20.0 h1:DIZnPsqzPGuUnq6cH8jWcPunBfY+C+M8JyYF3vpnuEo= +github.com/hashicorp/terraform-exec v0.20.0/go.mod h1:ckKGkJWbsNqFKV1itgMnE0hY9IYf1HoiekpuN0eWoDw= +github.com/hashicorp/terraform-json v0.21.0 h1:9NQxbLNqPbEMze+S6+YluEdXgJmhQykRyRNd+zTI05U= +github.com/hashicorp/terraform-json v0.21.0/go.mod h1:qdeBs11ovMzo5puhrRibdD6d2Dq6TyE/28JiU4tIQxk= +github.com/hashicorp/terraform-plugin-go v0.22.2 h1:5o8uveu6eZUf5J7xGPV0eY0TPXg3qpmwX9sce03Bxnc= +github.com/hashicorp/terraform-plugin-go v0.22.2/go.mod h1:drq8Snexp9HsbFZddvyLHN6LuWHHndSQg+gV+FPkcIM= github.com/hashicorp/terraform-plugin-log v0.9.0 h1:i7hOA+vdAItN1/7UrfBqBwvYPQ9TFvymaRGZED3FCV0= github.com/hashicorp/terraform-plugin-log v0.9.0/go.mod h1:rKL8egZQ/eXSyDqzLUuwUYLVdlYeamldAHSxjUFADow= github.com/hashicorp/terraform-plugin-sdk/v2 v2.33.0 h1:qHprzXy/As0rxedphECBEQAh3R4yp6pKksKHcqZx5G8= @@ -82,16 +91,13 @@ github.com/hashicorp/terraform-svchost v0.1.1 h1:EZZimZ1GxdqFRinZ1tpJwVxxt49xc/S github.com/hashicorp/terraform-svchost v0.1.1/go.mod h1:mNsjQfZyf/Jhz35v6/0LWcv26+X7JPS+buii2c9/ctc= github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE= github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= +github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= +github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/jhump/protoreflect v1.15.1 h1:HUMERORf3I3ZdX05WaQ6MIpd/NJ434hTp5YiKgfCL6c= github.com/jhump/protoreflect v1.15.1/go.mod h1:jD/2GMKKE6OqX8qTjhADU1e6DShO+gavG9e0Q693nKo= -github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns= -github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/compress v1.15.1/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= -github.com/klauspost/compress v1.15.12 h1:YClS/PImqYbn+UILDnqxQCZ3RehC9N318SU3kElDUEM= -github.com/klauspost/compress v1.15.12/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM= +github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= +github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= @@ -99,10 +105,6 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= -github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= -github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= @@ -122,14 +124,10 @@ github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyua github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= -github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= -github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA= github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU= +github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4= +github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -137,16 +135,13 @@ github.com/polds/imgbase64 v0.0.0-20140820003345-cb7bf37298b7 h1:AH5n8ganwKQPD8p github.com/polds/imgbase64 v0.0.0-20140820003345-cb7bf37298b7/go.mod h1:2Fh4ikMnX7lDL31/MpIly75tE6JIzJCV5bdSX3anemI= github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= -github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8= +github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= +github.com/skeema/knownhosts v1.2.2 h1:Iug2P4fLmDw9f41PB6thxUkNUkJzB5i+1/exaj40L3A= +github.com/skeema/knownhosts v1.2.2/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.7.2 h1:4jaiDzPyXQvSd7D0EjG45355tLlV3VOECpq10pLC+8s= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= -github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo= -github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= -github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs= -github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= github.com/vmihailenco/msgpack v4.0.4+incompatible h1:dSLoQfGFAo3F6OoNhwUmLwVgaUXK79GlxNBwueZn0xI= github.com/vmihailenco/msgpack v4.0.4+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= @@ -154,52 +149,39 @@ github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IU github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok= github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= -github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= +github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -github.com/zclconf/go-cty v1.14.2 h1:kTG7lqmBou0Zkx35r6HJHUQTvaRPr5bIAf3AoHS0izI= -github.com/zclconf/go-cty v1.14.2/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE= -go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= -go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= +github.com/zclconf/go-cty v1.14.4 h1:uXXczd9QDGsgu0i/QFR/hzI5NYCHLf6NQw/atrbnhq8= +github.com/zclconf/go-cty v1.14.4/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE= +github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b h1:FosyBZYxY34Wul7O/MSKey3txpPYyCqVO5ZyceuQJEI= +github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b/go.mod h1:ZRKQfBXbGkpdV6QMzT3rU1kSTAnfu1dO8dPKjYprgj8= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= +golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -212,46 +194,35 @@ golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuX golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.20.0 h1:hz/CVckiOxybQvFw6h7b/q80NTr9IUQb4s1IIzW7KNY= +golang.org/x/tools v0.20.0/go.mod h1:WvitBU7JJf6A4jOdg4S1tviW9bhUxkgeCui/0JHctQg= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= -google.golang.org/genproto/googleapis/rpc v0.0.0-20231106174013-bbf56f31fb17 h1:Jyp0Hsi0bmHXG6k9eATXoYtjd6e2UzZ1SCn/wIupY14= -google.golang.org/genproto/googleapis/rpc v0.0.0-20231106174013-bbf56f31fb17/go.mod h1:oQ5rr10WTTMvP4A36n8JpR1OrO1BEiV4f78CneXZxkA= -google.golang.org/grpc v1.61.1 h1:kLAiWrZs7YeDM6MumDe7m3y4aM6wacLzM1Y/wiLP9XY= -google.golang.org/grpc v1.61.1/go.mod h1:VUbo7IFqmF1QtCAstipjG0GIoq49KvMe9+h1jFLBNJs= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240415180920-8c6c420018be h1:LG9vZxsWGOmUKieR8wPAUR3u3MpnYFQZROPIMaXh7/A= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240415180920-8c6c420018be/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= +google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= +google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= -google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/go-playground/colors.v1 v1.2.0 h1:SPweMUve+ywPrfwao+UvfD5Ah78aOLUkT5RlJiZn52c= gopkg.in/go-playground/colors.v1 v1.2.0/go.mod h1:AvbqcMpNXVl5gBrM20jBm3VjjKBbH/kI5UnqjU7lxFI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= +gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -k8s.io/gengo v0.0.0-20220307231824-4627b89bbf1b/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= -k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= -nhooyr.io/websocket v1.8.7 h1:usjR2uOr/zjjkVMy0lW+PPohFok7PCow5sDjLgX4P4g= -nhooyr.io/websocket v1.8.7/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= -sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= diff --git a/main.go b/main.go index 4e899e5..00e1640 100644 --- a/main.go +++ b/main.go @@ -1,10 +1,22 @@ package main import ( + "flag" "github.com/hashicorp/terraform-plugin-sdk/v2/plugin" "github.com/lucky3028/discord-terraform/discord" ) +var ( + version string = "dev" +) + func main() { - plugin.Serve(&plugin.ServeOpts{ProviderFunc: discord.Provider}) + var debugMode bool + + flag.BoolVar(&debugMode, "debug", false, "set to true to run the provider with support for debuggers like delve") + flag.Parse() + plugin.Serve(&plugin.ServeOpts{ + ProviderFunc: discord.Provider(version), + Debug: debugMode, + }) }