Skip to content

Instantly share code, notes, and snippets.

@Necroforger
Last active March 19, 2019 09:59
Show Gist options
  • Save Necroforger/5a1a93c8c57c300bb1f112f4c1d7f01b to your computer and use it in GitHub Desktop.
Save Necroforger/5a1a93c8c57c300bb1f112f4c1d7f01b to your computer and use it in GitHub Desktop.
discord download emojis from all guilds
/*
download_emojis.go
https://gist.github.com/Necroforger/5a1a93c8c57c300bb1f112f4c1d7f01b
downloads emojis for all of the guilds a user or bot is in to a directory.
download_emojis -token <bot_token> [options]
options:
-n int
maximum number of simultaneous downloads (default 5)
-o string
output directory of emojis. default is the current working directory
-size string
size of emojis to download (default "32")
-token string
your bot token
*/
package main
import (
"errors"
"flag"
"fmt"
"io"
"log"
"net/http"
"os"
"path/filepath"
"sync"
_ "golang.org/x/image/bmp"
_ "image/gif"
_ "image/jpeg"
_ "image/png"
"github.com/bwmarrin/discordgo"
)
var (
token = flag.String("token", "", "your bot token")
dir = flag.String("o", "", "output directory of emojis. default is the current working directory")
size = flag.String("size", "32", "size of emojis to download")
nprocs = flag.Int("n", 5, "maximum number of simultaneous downloads")
)
// errors
var (
ErrEmojiAlreadySaved = errors.New("emoji already saved")
)
func emojiFilename(name, id, extension string) string {
return fmt.Sprintf("%s_%s%s", name, id, extension)
}
func downloadEmoji(e *discordgo.Emoji, size string, directory string) error {
var extension string
if e.Animated {
extension = ".gif"
} else {
extension = ".png"
}
// Stat the file to check if it exists. If the file does already exist, return
if f, err := os.Stat(filepath.Join(directory, emojiFilename(e.Name, e.ID, extension))); f != nil || os.IsExist(err) {
return ErrEmojiAlreadySaved
}
resp, err := http.Get(fmt.Sprintf(
"https://cdn.discordapp.com/emojis/%s%s?v=1&size=%s",
e.ID, extension, size))
if err != nil {
return err
}
if resp.StatusCode != 200 {
return errors.New(fmt.Sprint("HTTP did not respond with status 200: ", resp.StatusCode, http.StatusText(resp.StatusCode)))
}
defer resp.Body.Close()
f, err := os.OpenFile(
filepath.Join(
directory,
emojiFilename(e.Name, e.ID, extension),
),
os.O_CREATE|os.O_TRUNC|os.O_WRONLY,
0666,
)
if err != nil {
return err
}
defer f.Close()
_, err = io.Copy(f, resp.Body)
return err
}
func main() {
flag.Parse()
if *token == "" {
log.Fatal("please supply a user account or bot token to log in with")
}
log.Println("logging in with token: ", *token)
s, err := discordgo.New(*token)
if err != nil {
log.Fatal("error creating session: ", err)
}
err = s.Open()
if err != nil {
log.Fatal(err)
}
// Limit the number of concurrent downloads
semaphore := make(chan struct{}, *nprocs)
for i := 0; i < *nprocs; i++ {
semaphore <- struct{}{}
}
// Wait for all processes to complete
var wg sync.WaitGroup
log.Println("enumerating guilds and downloading emojis")
err = os.MkdirAll(*dir, 0666)
if err != nil && !os.IsExist(err) {
log.Fatal("error creating directory: ", err)
}
for _, v := range s.State.Guilds {
log.Println(v.Name, v.ID)
for _, e := range v.Emojis {
log.Println("\t", e.Name)
wg.Add(1)
<-semaphore
go func(e *discordgo.Emoji) {
err := downloadEmoji(e, *size, *dir)
if err != nil && err != ErrEmojiAlreadySaved {
log.Println("error downloading emoji: ", err)
}
semaphore <- struct{}{}
wg.Done()
}(e)
}
}
wg.Wait()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment