/*
|
|
* Archive Bot
|
|
* Copyright (c) 2020 Nichole Mattera
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*/
|
|
|
|
package main
|
|
|
|
import(
|
|
"encoding/json"
|
|
"flag"
|
|
"fmt"
|
|
"io"
|
|
"io/ioutil"
|
|
"net/http"
|
|
"os"
|
|
|
|
"github.com/bwmarrin/discordgo"
|
|
)
|
|
|
|
type Attachment struct {
|
|
Filename string `json:"filename"`
|
|
OriginalFilename string `json:"original_filename"`
|
|
}
|
|
|
|
type Message struct {
|
|
Attachments []Attachment `json:"attachments"`
|
|
AuthorID string `json:"author_id"`
|
|
Author string `json:"author"`
|
|
Content string `json:"content"`
|
|
Reactions []Reaction `json:"reactions"`
|
|
Timestamp string `json:"timestamp"`
|
|
}
|
|
|
|
type Reaction struct {
|
|
Name string `json:"name"`
|
|
Count int `json:"count"`
|
|
}
|
|
|
|
func main() {
|
|
var token string
|
|
var channelID string
|
|
var lastMessageID string
|
|
|
|
flag.StringVar(&token, "t", "", "The bot token. (Required)")
|
|
flag.StringVar(&channelID, "c", "", "The channel ID. (Required)")
|
|
flag.StringVar(&lastMessageID, "m", "", "The message ID to start archiving from, not including said message. If not specified it will archive all messages in the channel.")
|
|
|
|
flag.Parse()
|
|
|
|
if token == "" || channelID == "" {
|
|
fmt.Println("Usage:")
|
|
flag.PrintDefaults()
|
|
return
|
|
}
|
|
|
|
discord, err := discordgo.New("Bot " + token)
|
|
if err != nil {
|
|
fmt.Println("Error creating Discord session: ", err)
|
|
return
|
|
}
|
|
|
|
err = discord.Open()
|
|
if err != nil {
|
|
fmt.Println("error opening connection,", err)
|
|
return
|
|
}
|
|
|
|
if _, err := os.Stat("./pfps"); os.IsNotExist(err) {
|
|
os.Mkdir("./pfps", 0700)
|
|
}
|
|
|
|
if _, err := os.Stat("./" + channelID); os.IsNotExist(err) {
|
|
os.Mkdir("./" + channelID, 0700)
|
|
}
|
|
|
|
archivedMessages := []Message{}
|
|
numberOfMessages := 100
|
|
for numberOfMessages == 100 {
|
|
messages, err := discord.ChannelMessages(channelID, 100, lastMessageID, "", "")
|
|
if err != nil {
|
|
fmt.Println("error getting messages,", err)
|
|
return
|
|
}
|
|
|
|
for index, message := range messages {
|
|
// Download PfPs
|
|
if _, err := os.Stat("./pfps/" + message.Author.ID); os.IsNotExist(err) {
|
|
err = DownloadFile("./pfps/" + message.Author.ID, message.Author.AvatarURL(""))
|
|
|
|
if err != nil {
|
|
fmt.Println("error downloading PfP,", err)
|
|
}
|
|
}
|
|
|
|
// Build Attachments
|
|
archivedAttachments := []Attachment{}
|
|
for _, attachment := range message.Attachments {
|
|
if _, err := os.Stat("./" + channelID + "/" + message.ID + "_" + attachment.Filename); os.IsNotExist(err) {
|
|
err = DownloadFile("./" + channelID + "/" + message.ID + "_" + attachment.Filename, attachment.URL)
|
|
|
|
if err != nil {
|
|
fmt.Println("error downloading attachment,", err)
|
|
}
|
|
}
|
|
|
|
archivedAttachment := Attachment {
|
|
message.ID + "_" + attachment.Filename,
|
|
attachment.Filename,
|
|
}
|
|
|
|
archivedAttachments = append([]Attachment{ archivedAttachment }, archivedAttachments...)
|
|
}
|
|
|
|
// Build Reactions
|
|
archivedReactions := []Reaction{}
|
|
for _, reaction := range message.Reactions {
|
|
archivedReaction := Reaction {
|
|
reaction.Emoji.Name,
|
|
reaction.Count,
|
|
}
|
|
|
|
archivedReactions = append([]Reaction{ archivedReaction }, archivedReactions...)
|
|
}
|
|
|
|
archivedMessage := Message {
|
|
archivedAttachments,
|
|
message.Author.ID,
|
|
message.Author.Username + "#" + message.Author.Discriminator,
|
|
message.Content,
|
|
archivedReactions,
|
|
string(message.Timestamp),
|
|
}
|
|
|
|
archivedMessages = append([]Message{ archivedMessage }, archivedMessages...)
|
|
|
|
if index == len(messages) - 1 {
|
|
lastMessageID = message.ID
|
|
}
|
|
}
|
|
|
|
numberOfMessages = len(messages)
|
|
}
|
|
|
|
res, err := json.Marshal(archivedMessages)
|
|
if err != nil {
|
|
fmt.Println("error encoding messages to json,", err)
|
|
return
|
|
}
|
|
|
|
err = ioutil.WriteFile("./" + channelID + ".json", res, 0644)
|
|
|
|
discord.Close()
|
|
}
|
|
|
|
func DownloadFile(filepath string, url string) error {
|
|
// Get the data
|
|
resp, err := http.Get(url)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
// Create the file
|
|
out, err := os.Create(filepath)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer out.Close()
|
|
|
|
// Write the body to file
|
|
_, err = io.Copy(out, resp.Body)
|
|
return err
|
|
}
|