dwhook

package module
v0.0.0-...-0562c0c Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 3, 2021 License: Unlicense Imports: 18 Imported by: 5

README

DwHooks

DwHooks is a minimal library for sending discord webhook messages with no external dependencies outside of the discord service itself

for more info about webhooks see: https://discord.com/developers/docs/resources/webhook#execute-webhook

Feature support
  • Message content
  • Custom Usernames and avatars
  • Embeds
  • Allowed mentions
  • Sending files
  • Editing webhook messages
  • Deleting webhook messages
  • Ratelimits (Partal, X-Ratelimit-Bucket is not supported)

Usage examples

Some examples on how it works, full runnable code is included in the first simple example, but the function and package body will be left out of the following examples

Simple

for little things you can use the global functions to send a quick message, best used for little things

package main
import "codeberg.org/eviedelta/dwhook"

func main() {
	url := "WEBHOOK URL HERE"
	
	msg := dwhook.Message{
		Content: "This is an example for dwhook",
	}

	dwhook.SendTo(url, msg)
}
Custom Webhook object

for heavy use and/or use with more than one webhook it is recommended to create a seperate object with New or NewFromID, due to the default ratelimiting code not being able to take into account x-ratelimit-bucket

hook, err := dwhook.New("WEBHOOK URL")
if err != nil {
	fmt.Println("Invalid Webhook URL: ", err)
	return
}

msg := dwhook.Message{
	Content:  "Custom embed var",
}

hook.Send(msg)
Custom Username or Avatar
msg := dwhook.Message{
	Content:  "This is has a custom name and icon",

	Username:  "CustomName",
	AvatarURL:  "https://discord.com/assets/2c21aeda16de354ba5334551a883b481.png",  // discord icon
}
hook.Send(msg)
Embeds
msg := dwhook.Message{
	Embeds:  []dwhook.Embed{{
		Title:  "DwHook Example Embed",
		URL:  "codeberg.org/eviedelta/dwhook",
		Description:  "This is an embed constructed for example purposes",

		Fields:  []dwhook.EmbedField{{
			Name:  "this is an embed field",
			Value:  "Hello world",
		}},
		Footer: dwhook.EmbedFooter{
			Text:  "Footer",
		},
	}},
}
hook.Send(msg)
Delete message
hook.Delete(msgID)
Edit message
msg := dwhook.Message{
	Content: "This is an example edited message for dwhook",
}

hook.Edit(msg, msgID)

Documentation

Index

Constants

View Source
const (
	APIEndpoint        = connProtocol + "discord.com/api/v8/"
	APIEndpointWebhook = APIEndpoint + "webhooks/"
)

API Endpoints used internally

View Source
const (
	MentionRoles    = "roles"
	MentionUsers    = "users"
	MentionEveryone = "everyone"
)

Allowed mention types as based off of https://discord.com/developers/docs/resources/channel#allowed-mentions-object-allowed-mention-types

Variables

View Source
var (
	MaxMessages = 30
	MaxPeriod   = time.Minute
)

apparently there is a thing in the webhook api where you can only send 30 messages per minute to a channel but for whatever reason this is neither mentioned in the ratelimit headers nor the discord documentation, so unfortunetely i have to hard code this and hope for the best

View Source
var ErrorInvalidURL = errors.New("URL was invalid or could not be parsed")

ErrorInvalidURL is the error given when a URL does not pass validation regex

Functions

func DeleteTo

func DeleteTo(url, target string) ([]byte, error)

DeleteTo deletes a message from a specifed webhook

func DeleteToToken

func DeleteToToken(id, token string, target string) ([]byte, error)

DeleteToToken deletes a message from a specifed webhook

func EditTo

func EditTo(url string, message Message, target string) ([]byte, error)

EditTo edits a message from a specified discord webhook

func EditToToken

func EditToToken(id, token string, message Message, target string) ([]byte, error)

EditToToken edits a message from a specified discord webhook

func ParseWebhookURL

func ParseWebhookURL(url string) (id, token string, err error)

ParseWebhookURL parses a webhook url into its ID and token

func SendFileTo

func SendFileTo(url string, message Message, filename, contentType string, file []byte) ([]byte, error)

SendFileTo sends a message with a file to a specified discord webhook, for heavy use and/or use with more than one webhook it is recommended to create a seperate object with New or NewFromID due to how the ratelimiting code works

func SendFileToToken

func SendFileToToken(id, token string, message Message, filename, contentType string, file []byte) ([]byte, error)

SendFileToToken sends a message with a file to a specified discord webhook, for heavy use and/or use with more than one webhook it is recommended to create a seperate object with New or NewFromID due to how the ratelimiting code works

func SendFileToTokenWait

func SendFileToTokenWait(id, token string, message Message, filename, contentType string, file []byte) ([]byte, error)

SendFileToTokenWait sends a message with a file to a specified discord webhook and waits for the message data response

func SendFileToWait

func SendFileToWait(url string, message Message, filename, contentType string, file []byte) ([]byte, error)

SendFileToWait sends a message with a file to a specified discord webhook and waits for the message data response

func SendTo

func SendTo(url string, message Message) ([]byte, error)

SendTo sends a message to a specified discord webhook, for heavy use and/or use with more than one webhook it is recommended to create a seperate object with New or NewFromID due to how the ratelimiting code works

func SendToToken

func SendToToken(id, token string, message Message) ([]byte, error)

SendToToken sends a message to a specified discord webhook, for heavy use and/or use with more than one webhook it is recommended to create a seperate object with New or NewFromID due to how the ratelimiting code works

func SendToTokenWait

func SendToTokenWait(id, token string, message Message) ([]byte, error)

SendToTokenWait sends a message to a specified discord webhook and waits for the message data response

func SendToWait

func SendToWait(url string, message Message) ([]byte, error)

SendToWait sends a message to a specified discord webhook and waits for the message data response

func URLFromIDToken

func URLFromIDToken(id, token string) string

URLFromIDToken takes a webhook ID and token and returns an endpoint url for it

Types

type AllowedMentions

type AllowedMentions struct {
	// Allowed mention types, can use the consts MentionRoles MentionUsers or MentionEveryone here
	Parse []string `json:"parse"`

	// Users and Roles respectively take a list of User or Role IDs that are allowed to be mentioned
	Users []string `json:"users,omitempty"`
	Roles []string `json:"roles,omitempty"`
}

AllowedMentions allows more control over setting what can be mentioned within a message Original Documentation about how it works here https://discord.com/developers/docs/resources/channel#allowed-mentions-object

type Attachment

type Attachment struct {
	ID       string `json:"id"`
	Filename string `json:"filename"`
	Size     int    `json:"size"`
	URL      string `json:"url"`
	ProxyURL string `json:"proxy_url"`
	Height   int    `json:"height"`
	Width    int    `json:"width"`
}

Attachment object used for decoding full message objects

type Author

type Author struct {
	ID            string `json:"id"`
	Username      string `json:"username"`
	Discriminator string `json:"discriminator"`
	Avatar        string `json:"avatar,omitempty"`
	Bot           bool   `json:"bot"`
	System        bool   `json:"system"`
	Locale        string `json:"locale,omitempty"`
	Verified      bool   `json:"verified"`
	Flags         int    `json:"flags,omitempty"`
	PremiumType   int    `json:"premium_type,omitempty"`
	PublicFlags   int    `json:"public_flags,omitempty"`
}

Author object used only for decoding full message objects, basically a copy of the docs

type DefaultRatelimitHandler

type DefaultRatelimitHandler struct {
	// ResetTime and remaining reflect the standard ratelimit headers
	ResetTime time.Time
	Remaining int

	// mutual exclusion lock, technically redundent since the webhook itself is mutex'ed now but it is here just in case
	sync.RWMutex
	// contains filtered or unexported fields
}

DefaultRatelimitHandler is a default implementation of a ratelimit handler

func (*DefaultRatelimitHandler) Check

func (r *DefaultRatelimitHandler) Check(ctx context.Context, _ string) (wait time.Duration)

Check checks if there are no remaining requests that can be made and how long it should wait if so

func (*DefaultRatelimitHandler) Update

Update updates the ratelimit status

type Embed

type Embed struct {
	Title       string         `json:"title,omitempty"`
	Description string         `json:"description,omitempty"`
	URL         string         `json:"url,omitempty"`
	Timestamp   string         `json:"timestamp,omitempty"` // an ISO8601 or RFC3339 timestamp to mark the embed with
	Color       int            `json:"color,omitempty"`     // A color in RGB integer format (basically an RGB hex code converted to decimal)
	Footer      EmbedFooter    `json:"footer,omitempty"`
	Image       EmbedImage     `json:"image,omitempty"`
	Thumbnail   EmbedThumbnail `json:"thumbnail,omitempty"`
	Video       EmbedVideo     `json:"video,omitempty"`
	Author      EmbedAuthor    `json:"author,omitempty"`
	Fields      []EmbedField   `json:"fields,omitempty"`
}

Embed is the data for all discord embed fields

type EmbedAuthor

type EmbedAuthor struct {
	Name    string `json:"name,omitempty"`
	URL     string `json:"url,omitempty"`
	IconURL string `json:"icon_url,omitempty"`
}

EmbedAuthor contains data for the discord embed author field

type EmbedField

type EmbedField struct {
	Name   string `json:"name,omitempty"`
	Value  string `json:"value,omitempty"`
	Inline bool   `json:"inline,omitempty"`
}

EmbedField contains data for a discord embed field

type EmbedFooter

type EmbedFooter struct {
	Text    string `json:"text,omitempty"`
	IconURL string `json:"icon_url,omitempty"`
}

EmbedFooter contains data for a discord embed footer field

type EmbedImage

type EmbedImage struct {
	URL    string `json:"url,omitempty"`
	Height int    `json:"height,omitempty"`
	Width  int    `json:"width,omitempty"`
}

EmbedImage contains data for a discord embed image field

type EmbedThumbnail

type EmbedThumbnail struct {
	URL    string `json:"url,omitempty"`
	Height int    `json:"height,omitempty"`
	Width  int    `json:"width,omitempty"`
}

EmbedThumbnail contains data for a discord embed thumbnail field

type EmbedVideo

type EmbedVideo struct {
	URL    string `json:"url,omitempty"`
	Height int    `json:"height,omitempty"`
	Width  int    `json:"width,omitempty"`
}

EmbedVideo contains data for a discord embed video field

type Emoji

type Emoji struct {
	ID   string `json:"id"`
	Name string `json:"name"`
	// roles
	// user
	// require colons
	// managed
	Animated  bool `json:"animated"`
	Available bool `json:"available"`
}

Emoji object used for decoding full message objects

type FullMessage

type FullMessage struct {
	ID        string  `json:"id,omitempty"`
	ChannelID string  `json:"channel_id,omitempty"`
	GuildID   string  `json:"guild_id,omitempty"`
	Author    *Author `json:"author,omitempty"`
	//  Member          *Member       `json:"member,omitempty"`
	Content         string `json:"content,omitempty"`
	Timestamp       string `json:"timestamp,omitempty"`
	EditedTimestamp string `json:"edited_timestamp,omitempty"`
	// TTS             bool   `json:"tts"`
	MentionEveryone bool `json:"mention_everyone"`
	// Mentions
	// Mention roles
	// Mention channels
	Attachments []*Attachment `json:"attachments,omitempty"`
	Reactions   []*Reaction   `json:"reactions,omitempty"`
	// Nonce
	Pinned    bool   `json:"pinned"`
	WebhookID string `json:"webhook_id,omitempty"`
}

FullMessage this is only used for being able to decode the response if hook.SendWait is used without needing to define ones own structs or import something else Not all these fields may be useful or used, its just a copy of the reference in the discord docs If this lib is used in addition to another discord lib you can also unmarshal the response to the message structs offered by those

func EditToUnmarshal

func EditToUnmarshal(url string, message Message, target string) (*FullMessage, error)

EditToUnmarshal is like EditTo but it passes through UnmarshalResponse to give a message struct instead of bytes

func SendFileToUnmarshal

func SendFileToUnmarshal(url string, message Message, filename, contentType string, file []byte) (*FullMessage, error)

SendFileToUnmarshal is like SendFileTo but it passes through UnmarshalResponse to give a message struct instead of bytes

func SendToUnmarshal

func SendToUnmarshal(url string, message Message) (*FullMessage, error)

SendToUnmarshal is like SendToWait but it passes through UnmarshalResponse to give a message struct instead of bytes

func UnmarshalResponse

func UnmarshalResponse(b []byte, err error) (*FullMessage, error)

UnmarshalResponse is a utility function that one can chain the SendWait, SendFileWait or Edit function into to get a struct instead of just bytes Ex, dwhook.UnmarshalResponse(hook.SendWait(msg))

type Message

type Message struct {
	// The main message content
	Content string `json:"content,omitempty"`
	// Use a custom username, this can be left blank and it'll use the webhook name set on discords end
	Username string `json:"username,omitempty"`
	// URL to a custom avatar, this can be left blank and it'll use the avatar set on discords end
	AvatarURL string `json:"avatar_url,omitempty"`

	// A list of discord message embeds to include with the webhook
	Embeds []Embed `json:"embeds,omitempty"`

	// Discord allowed mentions object to allow more granular control over what can be mentioned
	AllowedMentions *AllowedMentions `json:"allowed_mentions,omitempty"`
}

Message defines the message format used by discords webhooks, almost all fields are entirely optional except for either content or embeds which at least one or the other must be set (you may have an embed but no content or content and no embed, however you cannot have neither)

type RatelimitHandler

type RatelimitHandler interface {

	// Check determines if a webhook should be limited or not
	// note that when not ratelimited it can only return 0 or less
	// a return of anything above 0 will cause the request loop to wait that amount of time and then reset to the beginning and check for limits again after the wait
	Check(ctx context.Context, webhookID string) (wait time.Duration)
	// Update gives an update to the ratelimit information
	Update(ctx context.Context, webhookID string, h http.Header) error
}

RatelimitHandler is the interface for implementations of a ratelimit handler

type Reaction

type Reaction struct {
	Count int   `json:"count"`
	Me    bool  `json:"me"`
	Emoji Emoji `json:"emoji"`
}

Reaction object used for decoding full message objects probably useless since reactions won't be on a newly posted message but here for completeness

type Webhook

type Webhook struct {
	Client    *http.Client
	ID, Token string

	R RatelimitHandler
	sync.Mutex
	// contains filtered or unexported fields
}

Webhook is a webhook client, its recommended you use New or NewFromID but you can create one directly if initiating one from a literal instead of the New functions it is required to call InitCheck at least once before using as that'll ensure a private var is set that would otherwise cause a panic if unset

func New

func New(url string) (*Webhook, error)

New returns a new webhook object with a set URL

func NewFromID

func NewFromID(id, token string) *Webhook

NewFromID is like ID but it takes a webhook token and ID

func (*Webhook) ActiveCount

func (w *Webhook) ActiveCount() int

ActiveCount gets whether there are currently webhook requests waiting to be sent

func (*Webhook) Delete

func (w *Webhook) Delete(message string) ([]byte, error)

Delete deletes a message

func (*Webhook) Edit

func (w *Webhook) Edit(contents Message, messageID string) ([]byte, error)

Edit a Message to the webhook URL in the Webhook client

func (*Webhook) EditUnmarshal

func (w *Webhook) EditUnmarshal(contents Message, messageID string) (*FullMessage, error)

EditUnmarshal is like Edit but it passes through UnmarshalResponse to give a message struct instead of just bytes

func (*Webhook) InitCheck

func (w *Webhook) InitCheck() error

InitCheck just verifies some private variables are set and sets them if they are not

func (*Webhook) Send

func (w *Webhook) Send(contents Message) ([]byte, error)

Send a Message to the webhook

func (*Webhook) SendFile

func (w *Webhook) SendFile(contents Message, filename, contentType string, file []byte) ([]byte, error)

SendFile a Message with file to the webhook

func (*Webhook) SendFileUnmarshal

func (w *Webhook) SendFileUnmarshal(contents Message, filename, contentType string, file []byte) (*FullMessage, error)

SendFileUnmarshal is like SendFileWait but it passes through UnmarshalResponse to give a message struct instead of bytes

func (*Webhook) SendFileWait

func (w *Webhook) SendFileWait(contents Message, filename, contentType string, file []byte) ([]byte, error)

SendFileWait a Message with file to the webhook URL in the Webhook client and wait to get the response

func (*Webhook) SendUnmarshal

func (w *Webhook) SendUnmarshal(contents Message) (*FullMessage, error)

SendUnmarshal is like SendWait but it passes through UnmarshalResponse to give a message struct instead of bytes

func (*Webhook) SendWait

func (w *Webhook) SendWait(contents Message) ([]byte, error)

SendWait a Message to the webhook and wait to get the message data

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL