Created
December 28, 2019 21:28
-
-
Save sug0/448612f9a14f2d2309e0ebf43a7ea45f to your computer and use it in GitHub Desktop.
Download discord channel messages
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package main | |
| import ( | |
| "os" | |
| "encoding/gob" | |
| "compress/gzip" | |
| "fmt" | |
| "github.com/bwmarrin/discordgo" | |
| ) | |
| func main() { | |
| f, err := os.Open(os.Args[1]) | |
| if err != nil { | |
| panic(err) | |
| } | |
| defer f.Close() | |
| gz, err := gzip.NewReader(f) | |
| if err != nil { | |
| panic(err) | |
| } | |
| defer gz.Close() | |
| var messages []*discordgo.Message | |
| err = gob.NewDecoder(gz).Decode(&messages) | |
| if err != nil { | |
| panic(err) | |
| } | |
| for _, m := range messages { | |
| fmt.Printf("[id=%s] %q said at %s: %s\n", m.ID, m.Author.Username, m.Timestamp, m.Content) | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package main | |
| import ( | |
| "os" | |
| "os/signal" | |
| "sort" | |
| "time" | |
| "encoding/gob" | |
| "compress/gzip" | |
| "path/filepath" | |
| "flag" | |
| "log" | |
| "fmt" | |
| "github.com/bwmarrin/discordgo" | |
| ) | |
| var ( | |
| msgCount uint64 | |
| startID string | |
| outputDir string | |
| discordToken string | |
| channelID string | |
| ) | |
| func init() { | |
| // necessary | |
| flag.StringVar(&outputDir, "o", "", "The output dir.") | |
| flag.StringVar(&discordToken, "t", "", "The discord token.") | |
| flag.StringVar(&channelID, "i", "", "The discord channel id.") | |
| // optional | |
| flag.StringVar(&startID, "s", "", "The message start id.") | |
| flag.Uint64Var(&msgCount, "c", 0, "The initial value for message count.") | |
| flag.Parse() | |
| // perform additional checks after parsing the flags | |
| switch { | |
| default: | |
| outputDir = filepath.Clean(outputDir) | |
| case outputDir == "": | |
| panic("No output dir specified.") | |
| case discordToken == "": | |
| panic("No discord token specified.") | |
| case channelID == "": | |
| panic("No discord channel id specified.") | |
| } | |
| } | |
| func main() { | |
| // open discord bot api | |
| dg, err := setupDiscord() | |
| if err != nil { | |
| panic(err) | |
| } | |
| defer dg.Close() | |
| // download first batch of messages | |
| msgs, err := getMessages(dg, startID) | |
| if err != nil { | |
| panic(err) | |
| } | |
| err = saveMessages(msgCount, msgs) | |
| if err != nil { | |
| panic(err) | |
| } | |
| // download the rest | |
| sigs := make(chan os.Signal, 8) | |
| signal.Notify(sigs, os.Kill, os.Interrupt) | |
| for { | |
| select { | |
| case <-sigs: | |
| return | |
| default: | |
| msgs, err = getMessages(dg, msgs[0].ID) | |
| if err != nil { | |
| panic(err) | |
| } | |
| if len(msgs) == 0 { | |
| return | |
| } | |
| msgCount += uint64(len(msgs)) | |
| go func(msgCount uint64, msgs []*discordgo.Message) { | |
| err := saveMessages(msgCount, msgs) | |
| if err != nil { | |
| panic(err) | |
| } | |
| }(msgCount, msgs) | |
| } | |
| } | |
| } | |
| func saveMessages(count uint64, msgs []*discordgo.Message) error { | |
| // filename | |
| path := fmt.Sprintf(`%s%c%024d.gob.gz`, outputDir, filepath.Separator, count) | |
| log.Printf("saving %s\n", path) | |
| // open file | |
| f, err := os.Create(path) | |
| if err != nil { | |
| return err | |
| } | |
| defer f.Close() | |
| // compressor | |
| gz := gzip.NewWriter(f) | |
| defer gz.Close() | |
| return gob.NewEncoder(gz).Encode(msgs) | |
| } | |
| func getMessages(dg *discordgo.Session, before string) ([]*discordgo.Message, error) { | |
| msgs, err := dg.ChannelMessages(channelID, -1, before, "", "") | |
| if err != nil { | |
| return nil, err | |
| } | |
| sort.Slice(msgs, func(i, j int) bool { | |
| ti, _ := time.Parse(time.RFC3339Nano, string(msgs[i].Timestamp)) | |
| tj, _ := time.Parse(time.RFC3339Nano, string(msgs[j].Timestamp)) | |
| return ti.Before(tj) | |
| }) | |
| return msgs, nil | |
| } | |
| func setupDiscord() (*discordgo.Session, error) { | |
| dg, err := discordgo.New(discordToken) | |
| if err != nil { | |
| return nil, err | |
| } | |
| err = dg.Open() | |
| if err != nil { | |
| return nil, err | |
| } | |
| return dg, nil | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment