Purpose built bot for archiving the AtlasNX Discord server. https://github.com/AtlasNX/Discord-Archive
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

187 lines
4.6 KiB

/*
* 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
}