Using Discord as your CDN.
Tags: go, webdev, tutorial
Published: 2022-12-16 14:31:56


![Gopher Discord](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kkk7o0wdq4x0euelkjmk.png)

Sometimes you are an indie developer or just creating a prototype, and you can't afford to set up a bucket on S3. For those times, I created this straightforward API to solve the issue of saving images in a database. 

You have to set up a bot, and the service will take care of the rest.

To save the images, you must send him a form post with the field ``file ``. The bot will save the photo and send it back as a URL so you can keep it in your database. In this blog post, I will explain what I've done and how you can set up for yourself this fantastic service.

> _Side note_:
> Thought that this post is not sponsored by [Meteor Cloud](https://www.meteor.com/cloud). I recommend their service, and they have a free tier where you have a MongoDB instance that can be used to save that URL I mentioned above.

## How to use it?

I will start linking the [source code repo](https://github.com/Grubba27/discord-as-cdn) and ask you to give it a star. 

If you want to run locally, you will need to set up a ``.env`` file with some info that the bot requires to work, and that is all. When you run the ``main`` function, it should create a web server where you can send a ``post`` request to it and store your photos dynamically. Again if you want a more detailed version of how to set up and run this service in your cloud infrastructure, you can check the [source code repo](https://github.com/Grubba27/discord-as-cdn). In this post, I will focus on how I did it.

## How is it done?

As you can see in the source code, this is a Go code, so it is straightforward as it can be.

### Creating HTTP server and Bot connection

In this first part of the ``main`` function, we have created the fiber HTTP server, and the creation of the ``/sendFile`` route. When this route is called, passing the ``file`` field, we have the creation of our discord bot using this excellent library called [discordgo](https://github.com/bwmarrin/discordgo). We also open the WebSocket to talk to the Discord servers.

```go
func main() {
	app := fiber.New()
	app.Use(cors.New())

	app.Post("/sendFile", func(ctx *fiber.Ctx) error {
		dg, err := discordgo.New("Bot " + os.Getenv("BOT_TOKEN"))

		if err != nil {
			fmt.Println("error creating Discord session,", err)
			return fiber.NewError(fiber.StatusBadRequest, "error creating Discord session")
		}

		err = dg.Open()
		if err != nil {
			fmt.Println("error opening connection,", err)
			return fiber.NewError(fiber.StatusBadRequest, "error opening connection,")

		}
```

### Getting the file and the channel 

After creating the bot, we need to check if the file can be transformed into a stream. We do size and file type checking.

```go

		file, err := ctx.FormFile("file")

		if err != nil {
			fmt.Println("Error getting file", err.Error())
			return fiber.NewError(fiber.StatusBadRequest, "Error getting file")
		}
		// do the checks and return a file to be sent to discord
		osFile, err := media.ToOSFile(ctx, file)
		if err != nil {
			fmt.Println("Error saving the file", err.Error())
			return fiber.NewError(fiber.StatusBadRequest, "Error saving the file")
		}


```
### Wrapping up and sending the URL

After doing all the necessary checks, we wrap the data into a struct that will be sent to discord and delivered to the bot. When sending the message is done, we gather the attachment URL and send it back to the user. We disconnect and clean up the server, so it is ready to receive another HTTP call.

```go

data := &discordgo.MessageSend{
			Files: []*discordgo.File{
				{
					Name:        file.Filename,
					ContentType: file.Header.Get("Content-Type"),
					Reader:      osFile,
				}},
		}

		msg, err := dg.ChannelMessageSendComplex(os.Getenv("CHANNEL_ID"), data)

		if err != nil {
			fmt.Println("Error sending the message ", err.Error())
			return fiber.NewError(fiber.StatusBadRequest, "Error sending the message")
		}

		r := new(Return)
		r.Url = msg.Attachments[0].URL

		// clean up and return
		if err := os.Remove(media.Path); err != nil {
			fmt.Println("Was not able to remove file", err.Error())
			return fiber.NewError(fiber.StatusBadRequest, "Was not able to remove file")
		}

		defer func(dg *discordgo.Session) {
			err := dg.Close()
			if err != nil {
				fmt.Println(err)
			}
		}(dg)
		return ctx.JSON(r)

	log.Fatal(app.Listen(":" + os.Getenv("PORT")))
}

```

## Conclusion

With less than 100 lines, you can set up a bot a discord bot and make it do extraordinary things for you. I hope that this blog post is helpful to you in any way!

If you did like this content, please follow me on [GitHub](https://github.com/Grubba27) and [Twitter](https://twitter.com/gab_grubba) for more! Also, liking this post will help me a lot. See you soon!