Browse Source

Add webhook support.

Chris Rhodes 8 years ago
parent
commit
ee3e500749
5 changed files with 274 additions and 26 deletions
  1. 6 0
      endpoints.go
  2. 65 23
      message.go
  3. 170 1
      restapi.go
  4. 1 1
      state.go
  5. 32 1
      structs.go

+ 6 - 0
endpoints.go

@@ -24,6 +24,7 @@ var (
 	EndpointChannels = EndpointAPI + "channels/"
 	EndpointUsers    = EndpointAPI + "users/"
 	EndpointGateway  = EndpointAPI + "gateway"
+	EndpointWebhooks = EndpointAPI + "webhooks/"
 
 	EndpointAuth           = EndpointAPI + "auth/"
 	EndpointLogin          = EndpointAuth + "login"
@@ -73,6 +74,7 @@ var (
 	EndpointGuildPrune           = func(gID string) string { return EndpointGuilds + gID + "/prune" }
 	EndpointGuildIcon            = func(gID, hash string) string { return EndpointGuilds + gID + "/icons/" + hash + ".jpg" }
 	EndpointGuildSplash          = func(gID, hash string) string { return EndpointGuilds + gID + "/splashes/" + hash + ".jpg" }
+	EndpointGuildWebhooks        = func(gID string) string { return EndpointGuilds + gID + "/webhooks" }
 
 	EndpointChannel                   = func(cID string) string { return EndpointChannels + cID }
 	EndpointChannelPermissions        = func(cID string) string { return EndpointChannels + cID + "/permissions" }
@@ -85,6 +87,10 @@ var (
 	EndpointChannelMessagesBulkDelete = func(cID string) string { return EndpointChannel(cID) + "/messages/bulk_delete" }
 	EndpointChannelMessagesPins       = func(cID string) string { return EndpointChannel(cID) + "/pins" }
 	EndpointChannelMessagePin         = func(cID, mID string) string { return EndpointChannel(cID) + "/pins/" + mID }
+	EndpointChannelWebhooks           = func(cID string) string { return EndpointChannel(cID) + "/webhooks" }
+
+	EndpointWebhook      = func(wID string) string { return EndpointWebhooks + wID }
+	EndpointWebhookToken = func(wID, token string) string { return EndpointWebhooks + wID + "/" + token }
 
 	EndpointInvite = func(iID string) string { return EndpointAPI + "invite/" + iID }
 

+ 65 - 23
message.go

@@ -41,31 +41,73 @@ type MessageAttachment struct {
 	Size     int    `json:"size"`
 }
 
+// MessageEmbedFooter is a part of a MessageEmbed struct.
+type MessageEmbedFooter struct {
+	Text         string `json:"text,omitempty"`
+	IconURL      string `json:"icon_url,omitempty"`
+	ProxyIconURL string `json:"proxy_icon_url,omitempty"`
+}
+
+// MessageEmbedImage is a part of a MessageEmbed struct.
+type MessageEmbedImage struct {
+	URL      string `json:"url,omitempty"`
+	ProxyURL string `json:"proxy_url,omitempty"`
+	Width    int    `json:"width,omitempty"`
+	Height   int    `json:"height,omitempty"`
+}
+
+// MessageEmbedThumbnail is a part of a MessageEmbed struct.
+type MessageEmbedThumbnail struct {
+	URL      string `json:"url,omitempty"`
+	ProxyURL string `json:"proxy_url,omitempty"`
+	Width    int    `json:"width,omitempty"`
+	Height   int    `json:"height,omitempty"`
+}
+
+// MessageEmbedVideo is a part of a MessageEmbed struct.
+type MessageEmbedVideo struct {
+	URL      string `json:"url,omitempty"`
+	ProxyURL string `json:"proxy_url,omitempty"`
+	Width    int    `json:"width,omitempty"`
+	Height   int    `json:"height,omitempty"`
+}
+
+// MessageEmbedProvider is a part of a MessageEmbed struct.
+type MessageEmbedProvider struct {
+	URL  string `json:"url,omitempty"`
+	Name string `json:"name,omitempty"`
+}
+
+// MessageEmbedAuthor is a part of a MessageEmbed struct.
+type MessageEmbedAuthor struct {
+	URL          string `json:"url,omitempty"`
+	Name         string `json:"name,omitempty"`
+	IconURL      string `json:"icon_url,omitempty"`
+	ProxyIconURL string `json:"proxy_icon_url,omitempty"`
+}
+
+// MessageEmbedField is a part of a MessageEmbed struct.
+type MessageEmbedField struct {
+	Name   string `json:"name,omitempty"`
+	Value  string `json:"value,omitempty"`
+	Inline bool   `json:"inline,omitempty"`
+}
+
 // An MessageEmbed stores data for message embeds.
 type MessageEmbed struct {
-	URL         string `json:"url"`
-	Type        string `json:"type"`
-	Title       string `json:"title"`
-	Description string `json:"description"`
-	Thumbnail   *struct {
-		URL      string `json:"url"`
-		ProxyURL string `json:"proxy_url"`
-		Width    int    `json:"width"`
-		Height   int    `json:"height"`
-	} `json:"thumbnail"`
-	Provider *struct {
-		URL  string `json:"url"`
-		Name string `json:"name"`
-	} `json:"provider"`
-	Author *struct {
-		URL  string `json:"url"`
-		Name string `json:"name"`
-	} `json:"author"`
-	Video *struct {
-		URL    string `json:"url"`
-		Width  int    `json:"width"`
-		Height int    `json:"height"`
-	} `json:"video"`
+	URL         string                 `json:"url,omitempty"`
+	Type        string                 `json:"type,omitempty"`
+	Title       string                 `json:"title,omitempty"`
+	Description string                 `json:"description,omitempty"`
+	Timestamp   string                 `json:"timestamp,omitempty"`
+	Color       int                    `json:"color,omitempty"`
+	Footer      *MessageEmbedFooter    `json:"footer,omitempty"`
+	Image       *MessageEmbedImage     `json:"image,omitempty"`
+	Thumbnail   *MessageEmbedThumbnail `json:"thumbnail,omitempty"`
+	Video       *MessageEmbedVideo     `json:"video,omitempty"`
+	Provider    *MessageEmbedProvider  `json:"provider,omitempty"`
+	Author      *MessageEmbedAuthor    `json:"author,omitempty"`
+	Fields      []*MessageEmbedField   `json:"fields,omitempty"`
 }
 
 // ContentWithMentionsReplaced will replace all @<id> mentions with the

+ 170 - 1
restapi.go

@@ -440,7 +440,7 @@ func (s *Session) UserChannelPermissions(userID, channelID string) (apermissions
 		}
 	}
 
-	if apermissions&PermissionManageRoles > 0 {
+	if apermissions&PermissionAdministrator > 0 {
 		apermissions |= PermissionAll
 	}
 
@@ -1439,3 +1439,172 @@ func (s *Session) Gateway() (gateway string, err error) {
 	gateway = temp.URL
 	return
 }
+
+// Functions specific to Webhooks
+
+// WebhookCreate returns a new Webhook.
+// channelID: The ID of a Channel.
+// name     : The name of the webhook.
+// avatar   : The avatar of the webhook.
+func (s *Session) WebhookCreate(channelID, name, avatar string) (st *Webhook, err error) {
+
+	data := struct {
+		Name   string `json:"name"`
+		Avatar string `json:"avatar,omitempty"`
+	}{name, avatar}
+
+	body, err := s.Request("POST", EndpointChannelWebhooks(channelID), data)
+	if err != nil {
+		return
+	}
+
+	err = unmarshal(body, &st)
+
+	return
+}
+
+// ChannelWebhooks returns all webhooks for a given channel.
+// channelID: The ID of a channel.
+func (s *Session) ChannelWebhooks(channelID string) (st []*Webhook, err error) {
+
+	body, err := s.Request("GET", EndpointChannelWebhooks(channelID), nil)
+	if err != nil {
+		return
+	}
+
+	err = unmarshal(body, &st)
+
+	return
+}
+
+// GuildWebhooks returns all webhooks for a given guild.
+// guildID: The ID of a Guild.
+func (s *Session) GuildWebhooks(guildID string) (st []*Webhook, err error) {
+
+	body, err := s.Request("GET", EndpointGuildWebhooks(guildID), nil)
+	if err != nil {
+		return
+	}
+
+	err = unmarshal(body, &st)
+
+	return
+}
+
+// Webhook returns a webhook for a given ID
+// webhookID: The ID of a webhook.
+func (s *Session) Webhook(webhookID string) (st *Webhook, err error) {
+
+	body, err := s.Request("GET", EndpointWebhook(webhookID), nil)
+	if err != nil {
+		return
+	}
+
+	err = unmarshal(body, &st)
+
+	return
+}
+
+// WebhookWithToken returns a webhook for a given ID
+// webhookID: The ID of a webhook.
+// token    : The auth token for the webhook.
+func (s *Session) WebhookWithToken(webhookID, token string) (st *Webhook, err error) {
+
+	body, err := s.Request("GET", EndpointWebhookToken(webhookID, token), nil)
+	if err != nil {
+		return
+	}
+
+	err = unmarshal(body, &st)
+
+	return
+}
+
+// WebhookEdit updates an existing Webhook.
+// webhookID: The ID of a webhook.
+// name     : The name of the webhook.
+// avatar   : The avatar of the webhook.
+func (s *Session) WebhookEdit(webhookID, name, avatar string) (st *Role, err error) {
+
+	data := struct {
+		Name   string `json:"name,omitempty"`
+		Avatar string `json:"avatar,omitempty"`
+	}{name, avatar}
+
+	body, err := s.Request("PATCH", EndpointWebhook(webhookID), data)
+	if err != nil {
+		return
+	}
+
+	err = unmarshal(body, &st)
+
+	return
+}
+
+// WebhookEditWithToken updates an existing Webhook with an auth token.
+// webhookID: The ID of a webhook.
+// token    : The auth token for the webhook.
+// name     : The name of the webhook.
+// avatar   : The avatar of the webhook.
+func (s *Session) WebhookEditWithToken(webhookID, token, name, avatar string) (st *Role, err error) {
+
+	data := struct {
+		Name   string `json:"name,omitempty"`
+		Avatar string `json:"avatar,omitempty"`
+	}{name, avatar}
+
+	body, err := s.Request("PATCH", EndpointWebhookToken(webhookID, token), data)
+	if err != nil {
+		return
+	}
+
+	err = unmarshal(body, &st)
+
+	return
+}
+
+// WebhookDelete deletes a webhook for a given ID
+// webhookID: The ID of a webhook.
+func (s *Session) WebhookDelete(webhookID string) (st *Webhook, err error) {
+
+	body, err := s.Request("DELETE", EndpointWebhook(webhookID), nil)
+	if err != nil {
+		return
+	}
+
+	err = unmarshal(body, &st)
+
+	return
+}
+
+// WebhookDeleteWithToken deletes a webhook for a given ID with an auth token.
+// webhookID: The ID of a webhook.
+// token    : The auth token for the webhook.
+func (s *Session) WebhookDeleteWithToken(webhookID, token string) (st *Webhook, err error) {
+
+	body, err := s.Request("DELETE", EndpointWebhookToken(webhookID, token), nil)
+	if err != nil {
+		return
+	}
+
+	err = unmarshal(body, &st)
+
+	return
+}
+
+// WebhookExecute executes a webhook.
+// webhookID: The ID of a webhook.
+// token    : The auth token for the bebhook
+func (s *Session) WebhookExecute(webhookID, token string, wait bool, data *WebhookParams) (err error) {
+	uri := EndpointWebhookToken(webhookID, token)
+
+	if wait {
+		uri += "?wait=true"
+	}
+
+	fmt.Println(uri)
+
+	_, err = s.Request("POST", uri, data)
+
+	return
+}

+ 1 - 1
state.go

@@ -755,7 +755,7 @@ func (s *State) UserChannelPermissions(userID, channelID string) (apermissions i
 		}
 	}
 
-	if apermissions&PermissionManageRoles > 0 {
+	if apermissions&PermissionAdministrator > 0 {
 		apermissions |= PermissionAll
 	}
 

+ 32 - 1
structs.go

@@ -489,6 +489,27 @@ type ChannelPinsUpdate struct {
 	ChannelID        string `json:"channel_id"`
 }
 
+// Webhook stores the data for a webhook.
+type Webhook struct {
+	ID        string `json:"id"`
+	GuildID   string `json:"guild_id"`
+	ChannelID string `json:"channel_id"`
+	User      *User  `json:"user"`
+	Name      string `json:"name"`
+	Avatar    string `json:"avatar"`
+	Token     string `json:"token"`
+}
+
+// WebhookParams is a struct for webhook params, used in the WebhookExecute command.
+type WebhookParams struct {
+	Content   string          `json:"content,omitempty"`
+	Username  string          `json:"username,omitempty"`
+	AvatarURL string          `json:"avatar_url,omitempty"`
+	TTS       bool            `json:"tts,omitempty"`
+	File      string          `json:"file,omitempty"`
+	Embeds    []*MessageEmbed `json:"embeds,omitempty"`
+}
+
 // Constants for the different bit offsets of text channel permissions
 const (
 	PermissionReadMessages = 1 << (iota + 10)
@@ -499,6 +520,7 @@ const (
 	PermissionAttachFiles
 	PermissionReadMessageHistory
 	PermissionMentionEveryone
+	PermissionUseExternalEmojis
 )
 
 // Constants for the different bit offsets of voice permissions
@@ -511,12 +533,21 @@ const (
 	PermissionVoiceUseVAD
 )
 
+// Constants for general management.
+const (
+	PermissionChangeNickname = 1 << (iota + 26)
+	PermissionManageNicknames
+	PermissionManageRoles
+	PermissionManageWebhooks
+	PermissionManageEmojis
+)
+
 // Constants for the different bit offsets of general permissions
 const (
 	PermissionCreateInstantInvite = 1 << iota
 	PermissionKickMembers
 	PermissionBanMembers
-	PermissionManageRoles
+	PermissionAdministrator
 	PermissionManageChannels
 	PermissionManageServer