diff --git a/config.template.json b/config.template.json index 268bbc8..3d3e01d 100644 --- a/config.template.json +++ b/config.template.json @@ -11,7 +11,8 @@ "jwt_key": "", "server_addr": "0.0.0.0:80", - "logging": true, + "logger": true, + "database": "data.db", "sounds_path": "./sounds/", "clips_path": "./clips/" diff --git a/main.go b/main.go index 23aca4e..87cd276 100644 --- a/main.go +++ b/main.go @@ -1,12 +1,15 @@ package main import ( + "os" + "github.com/gin-gonic/gin" "github.com/mgerb/go-discord-bot/server/bot" "github.com/mgerb/go-discord-bot/server/config" + "github.com/mgerb/go-discord-bot/server/db" + "github.com/mgerb/go-discord-bot/server/logger" "github.com/mgerb/go-discord-bot/server/webserver" log "github.com/sirupsen/logrus" - "os" ) func init() { @@ -23,6 +26,11 @@ func init() { // Only log the warning severity or above. log.SetLevel(log.WarnLevel) } + + if config.Config.Logger { + db.Init() + db.Conn.AutoMigrate(&logger.Message{}, &logger.Attachment{}, &logger.User{}) + } } func main() { diff --git a/server/bot/bot.go b/server/bot/bot.go index 1e45f9c..fd57309 100644 --- a/server/bot/bot.go +++ b/server/bot/bot.go @@ -3,18 +3,26 @@ package bot import ( "github.com/bwmarrin/discordgo" "github.com/mgerb/go-discord-bot/server/bothandlers" + "github.com/mgerb/go-discord-bot/server/config" log "github.com/sirupsen/logrus" ) -func Start(token string) { +// Start the bot +func Start(token string) *discordgo.Session { // initialize connection session := connect(token) // add bot handlers addHandler(session, bothandlers.SoundsHandler) + if config.Config.Logger { + addHandler(session, bothandlers.LoggerHandler) + } + // start listening for commands startListener(session) + + return session } func addHandler(session *discordgo.Session, handler interface{}) { diff --git a/server/bothandlers/logger.go b/server/bothandlers/logger.go new file mode 100644 index 0000000..e71abab --- /dev/null +++ b/server/bothandlers/logger.go @@ -0,0 +1,68 @@ +package bothandlers + +import ( + "strconv" + "strings" + + "github.com/bwmarrin/discordgo" + "github.com/mgerb/go-discord-bot/server/logger" +) + +// LoggerHandler - +func LoggerHandler(s *discordgo.Session, m *discordgo.MessageCreate) { + + // upsert user + user := getUser(m.Author) + user.Save() + + // create and save message + timestamp, _ := m.Message.Timestamp.Parse() + editedTimestamp, _ := m.Message.EditedTimestamp.Parse() + attachments := getAttachments(m.Message.Attachments) + + message := &logger.Message{ + ID: m.Message.ID, + ChannelID: m.Message.ChannelID, + Content: m.Message.Content, + Timestamp: strconv.Itoa(int(timestamp.Unix())), + EditedTimestamp: strconv.Itoa(int(editedTimestamp.Unix())), + MentionRoles: strings.Join(m.Message.MentionRoles, ","), + Tts: m.Message.Tts, + MentionEveryone: m.Message.MentionEveryone, + UserID: m.Author.ID, + Attachments: attachments, + } + + message.Save() +} + +func getAttachments(att []*discordgo.MessageAttachment) []logger.Attachment { + var attachments []logger.Attachment + for _, a := range att { + newAttachment := logger.Attachment{ + MessageID: a.ID, + Filename: a.Filename, + Height: a.Height, + ProxyURL: a.ProxyURL, + Size: a.Size, + URL: a.URL, + Width: a.Width, + } + attachments = append(attachments, newAttachment) + } + return attachments +} + +func getUser(u *discordgo.User) *logger.User { + return &logger.User{ + ID: u.ID, + Email: u.Email, + Username: u.Username, + Avatar: u.Avatar, + Discriminator: u.Discriminator, + Token: u.Token, + Verified: u.Verified, + MFAEnabled: u.MFAEnabled, + Bot: u.Bot, + } +} diff --git a/server/config/config.go b/server/config/config.go index 27a51c0..609568c 100644 --- a/server/config/config.go +++ b/server/config/config.go @@ -31,7 +31,8 @@ type configFile struct { ServerAddr string `json:"server_addr"` JWTKey string `json:"jwt_key"` - Logging bool `json:"logging"` + Logger bool `json:"logger"` + Database string `json:"database"` } type configFlags struct { diff --git a/server/db/db.go b/server/db/db.go new file mode 100644 index 0000000..c3fbfef --- /dev/null +++ b/server/db/db.go @@ -0,0 +1,24 @@ +package db + +import ( + "github.com/jinzhu/gorm" + "github.com/mgerb/go-discord-bot/server/config" + + // database driver for sqlite + _ "github.com/jinzhu/gorm/dialects/sqlite" +) + +// Conn - database connection +var Conn *gorm.DB + +// Init - initialize database +func Init() { + var err error + Conn, err = gorm.Open("sqlite3", config.Config.Database) + + if err != nil { + panic("failed to connect database") + } + + Conn.DB().SetMaxIdleConns(1) +} diff --git a/server/logger/logger.go b/server/logger/logger.go new file mode 100644 index 0000000..a66a6cf --- /dev/null +++ b/server/logger/logger.go @@ -0,0 +1,59 @@ +package logger + +import ( + "time" + + "github.com/mgerb/go-discord-bot/server/db" +) + +// Message - discord message +type Message struct { + ID string `gorm:"primary_key" json:"id"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` + DeletedAt *time.Time `json:"deleted_at"` + ChannelID string `json:"channel_id"` + Content string `json:"content"` + Timestamp string `json:"timestamp"` + EditedTimestamp string `json:"edited_timestamp"` + MentionRoles string `json:"mention_roles"` + Tts bool `json:"tts"` + MentionEveryone bool `json:"mention_everyone"` + User User `json:"user"` + UserID string `json:"user_id"` + Attachments []Attachment `json:"attachments"` +} + +// Save - +func (m *Message) Save() error { + return db.Conn.Save(m).Error +} + +// Attachment - discord message attachment +type Attachment struct { + MessageID string `gorm:"primary_key" json:"id"` + URL string `json:"url"` + ProxyURL string `json:"proxy_url"` + Filename string `json:"filename"` + Width int `json:"width"` + Height int `json:"height"` + Size int `json:"size"` +} + +// User - +type User struct { + ID string `gorm:"primary_key" json:"id"` + Email string `json:"email"` + Username string `json:"username"` + Avatar string `json:"avatar"` + Discriminator string `json:"discriminator"` + Token string `json:"token"` + Verified bool `json:"verified"` + MFAEnabled bool `json:"mfa_enabled"` + Bot bool `json:"bot"` +} + +// Save - +func (u *User) Save() error { + return db.Conn.Save(u).Error +} diff --git a/server/scripts/restore_messages.go b/server/scripts/restore_messages.go new file mode 100644 index 0000000..96e59fa --- /dev/null +++ b/server/scripts/restore_messages.go @@ -0,0 +1,43 @@ +package main + +import ( + "log" + + "github.com/bwmarrin/discordgo" + "github.com/mgerb/go-discord-bot/server/bot" + "github.com/mgerb/go-discord-bot/server/bothandlers" + "github.com/mgerb/go-discord-bot/server/config" + "github.com/mgerb/go-discord-bot/server/db" +) + +const everyoneChannel = "101198129352691712" + +// this is a script to go through chat history and log old message into database +func main() { + config.Init() + db.Init() + session := bot.Start(config.Config.Token) + fetchMessages(session, "") +} + +func fetchMessages(s *discordgo.Session, beforeID string) { + + messages, err := s.ChannelMessages(everyoneChannel, 100, beforeID, "", "") + + log.Println("Fetching new messages: " + messages[0].Timestamp) + + if err != nil { + log.Fatal(err) + } + + for _, m := range messages { + messageCreate := &discordgo.MessageCreate{ + Message: m, + } + bothandlers.LoggerHandler(s, messageCreate) + } + + if len(messages) == 100 { + fetchMessages(s, messages[len(messages)-1].ID) + } +} diff --git a/server/webserver/handlers/logger.go b/server/webserver/handlers/logger.go new file mode 100644 index 0000000..cefe70a --- /dev/null +++ b/server/webserver/handlers/logger.go @@ -0,0 +1,28 @@ +package handlers + +import ( + "strconv" + + "github.com/gin-gonic/gin" + "github.com/mgerb/go-discord-bot/server/db" + "github.com/mgerb/go-discord-bot/server/logger" +) + +// GetLogs - get all logs +func GetLogs(c *gin.Context) { + page, err := strconv.Atoi(c.Query("page")) + + if err != nil { + page = 0 + } + + messages := []logger.Message{} + err = db.Conn.Offset(page*100).Limit(100).Order("timestamp desc", true).Preload("User").Find(&messages).Error + + if err != nil { + c.JSON(500, err) + return + } + + c.JSON(200, messages) +} diff --git a/server/webserver/server.go b/server/webserver/server.go index 8868389..ac50dab 100644 --- a/server/webserver/server.go +++ b/server/webserver/server.go @@ -23,6 +23,7 @@ func getRouter() *gin.Engine { api.GET("/ytdownloader", handlers.Downloader) api.GET("/soundlist", handlers.SoundList) api.GET("/cliplist", handlers.ClipList) + api.GET("/logs", handlers.GetLogs) api.POST("/oauth", handlers.Oauth) authorizedAPI := router.Group("/api")