github.com/diamondburned/arikawa/v2@v2.1.0/_example/advanced_bot/bot.go (about)

     1  package main
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"fmt"
     7  	"strconv"
     8  	"strings"
     9  	"time"
    10  
    11  	"github.com/diamondburned/arikawa/v2/bot"
    12  	"github.com/diamondburned/arikawa/v2/bot/extras/arguments"
    13  	"github.com/diamondburned/arikawa/v2/bot/extras/middlewares"
    14  	"github.com/diamondburned/arikawa/v2/discord"
    15  	"github.com/diamondburned/arikawa/v2/gateway"
    16  )
    17  
    18  type Bot struct {
    19  	// Context must not be embedded.
    20  	Ctx *bot.Context
    21  }
    22  
    23  func (bot *Bot) Setup(sub *bot.Subcommand) {
    24  	// Only allow people in guilds to run guildInfo.
    25  	sub.AddMiddleware(bot.GuildInfo, middlewares.GuildOnly(bot.Ctx))
    26  }
    27  
    28  // Help prints the default help message.
    29  func (bot *Bot) Help(*gateway.MessageCreateEvent) (string, error) {
    30  	return bot.Ctx.Help(), nil
    31  }
    32  
    33  // Add demonstrates the usage of typed arguments. Run it with "~add 1 2".
    34  func (bot *Bot) Add(_ *gateway.MessageCreateEvent, a, b int) (string, error) {
    35  	return fmt.Sprintf("%d + %d = %d", a, b, a+b), nil
    36  }
    37  
    38  // Ping is a simple ping example, perhaps the most simple you could make it.
    39  func (bot *Bot) Ping(*gateway.MessageCreateEvent) (string, error) {
    40  	return "Pong!", nil
    41  }
    42  
    43  // Say demonstrates how arguments.Flag could be used without the flag library.
    44  func (bot *Bot) Say(_ *gateway.MessageCreateEvent, f bot.RawArguments) (string, error) {
    45  	if f != "" {
    46  		return string(f), nil
    47  	}
    48  	return "", errors.New("missing content")
    49  }
    50  
    51  // GuildInfo demonstrates the GuildOnly middleware done in (*Bot).Setup().
    52  func (bot *Bot) GuildInfo(m *gateway.MessageCreateEvent) (string, error) {
    53  	g, err := bot.Ctx.GuildWithCount(m.GuildID)
    54  	if err != nil {
    55  		return "", fmt.Errorf("failed to get guild: %v", err)
    56  	}
    57  
    58  	return fmt.Sprintf(
    59  		"Your guild is %s, and its maximum members is %d",
    60  		g.Name, g.ApproximateMembers,
    61  	), nil
    62  }
    63  
    64  // Repeat tells the bot to wait for the user's response, then repeat what they
    65  // said.
    66  func (bot *Bot) Repeat(m *gateway.MessageCreateEvent) (string, error) {
    67  	_, err := bot.Ctx.SendMessage(m.ChannelID, "What do you want me to say?", nil)
    68  	if err != nil {
    69  		return "", err
    70  	}
    71  
    72  	ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
    73  	defer cancel()
    74  
    75  	// This might miss events that are sent immediately after. To make sure all
    76  	// events are caught, ChanFor should be used.
    77  	v := bot.Ctx.WaitFor(ctx, func(v interface{}) bool {
    78  		// Incoming event is a message create event:
    79  		mg, ok := v.(*gateway.MessageCreateEvent)
    80  		if !ok {
    81  			return false
    82  		}
    83  
    84  		// Message is from the same author:
    85  		return mg.Author.ID == m.Author.ID
    86  	})
    87  
    88  	if v == nil {
    89  		return "", errors.New("timed out waiting for response")
    90  	}
    91  
    92  	ev := v.(*gateway.MessageCreateEvent)
    93  	return ev.Content, nil
    94  }
    95  
    96  // Embed is a simple embed creator. Its purpose is to demonstrate the usage of
    97  // the ParseContent interface, as well as using the stdlib flag package.
    98  func (bot *Bot) Embed(_ *gateway.MessageCreateEvent, f arguments.Flag) (*discord.Embed, error) {
    99  	fs := arguments.NewFlagSet()
   100  
   101  	var (
   102  		title  = fs.String("title", "", "Title")
   103  		author = fs.String("author", "", "Author")
   104  		footer = fs.String("footer", "", "Footer")
   105  		color  = fs.String("color", "#FFFFFF", "Color in hex format #hhhhhh")
   106  	)
   107  
   108  	if err := f.With(fs.FlagSet); err != nil {
   109  		return nil, err
   110  	}
   111  
   112  	if len(fs.Args()) < 1 {
   113  		return nil, fmt.Errorf("usage: embed [flags] content...\n" + fs.Usage())
   114  	}
   115  
   116  	// Check if the color string is valid.
   117  	if !strings.HasPrefix(*color, "#") || len(*color) != 7 {
   118  		return nil, errors.New("invalid color, format must be #hhhhhh")
   119  	}
   120  
   121  	// Parse the color into decimal numbers.
   122  	colorHex, err := strconv.ParseInt((*color)[1:], 16, 64)
   123  	if err != nil {
   124  		return nil, err
   125  	}
   126  
   127  	// Make a new embed
   128  	embed := discord.Embed{
   129  		Title:       *title,
   130  		Description: strings.Join(fs.Args(), " "),
   131  		Color:       discord.Color(colorHex),
   132  	}
   133  
   134  	if *author != "" {
   135  		embed.Author = &discord.EmbedAuthor{
   136  			Name: *author,
   137  		}
   138  	}
   139  	if *footer != "" {
   140  		embed.Footer = &discord.EmbedFooter{
   141  			Text: *footer,
   142  		}
   143  	}
   144  
   145  	return &embed, err
   146  }