diff --git a/client/app/pages/Soundboard/Soundboard.tsx b/client/app/pages/Soundboard/Soundboard.tsx index 5d83aad..a672ddc 100644 --- a/client/app/pages/Soundboard/Soundboard.tsx +++ b/client/app/pages/Soundboard/Soundboard.tsx @@ -82,7 +82,7 @@ export class Soundboard extends React.Component { formData.append("file", file); formData.append("password", this.state.password); - axios.put("/api/upload", formData, this.config) + axios.post("/api/upload", formData, this.config) .then(() => { this.setState({ password: "", diff --git a/main.go b/main.go index 4fa1d76..8f00f1c 100644 --- a/main.go +++ b/main.go @@ -1,16 +1,39 @@ package main import ( + "github.com/gin-gonic/gin" "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/webserver" + log "github.com/sirupsen/logrus" + "os" ) -func main() { +func init() { //read config file config.Init() + // Log as JSON instead of the default ASCII formatter. + log.SetFormatter(&log.JSONFormatter{}) + + // Output to stdout instead of the default stderr + // Can be any io.Writer, see below for File example + log.SetOutput(os.Stdout) + + if config.Flags.Prod { + // prod + gin.SetMode(gin.ReleaseMode) + // Only log the warning severity or above. + log.SetLevel(log.WarnLevel) + } else { + // debug + log.SetLevel(log.DebugLevel) + } +} + +func main() { + //connect bot to account with token bot.Connect(config.Config.Token) diff --git a/server/bot/bot.go b/server/bot/bot.go index 5da0675..8dee48d 100644 --- a/server/bot/bot.go +++ b/server/bot/bot.go @@ -1,10 +1,8 @@ package bot import ( - "fmt" - "log" - "github.com/bwmarrin/discordgo" + log "github.com/sirupsen/logrus" ) // Variables used for command line parameters @@ -19,7 +17,7 @@ func Connect(token string) { Session, err = discordgo.New("Bot " + token) if err != nil { - log.Println(err) + log.Error(err) log.Fatal("Error creating Discord session.", err) } @@ -27,14 +25,14 @@ func Connect(token string) { u, err := Session.User("@me") if err != nil { - log.Println("Error obtaining account details. Make sure you have the correct bot token.") + log.Error("Error obtaining account details. Make sure you have the correct bot token.") log.Fatal(err) } // Store the account ID for later use. BotID = u.ID - fmt.Println("Bot connected") + log.Debug("Bot connected") } // Start - blocking function that starts a websocket listenting for discord callbacks @@ -45,11 +43,11 @@ func Start() { // Open the websocket and begin listening. err := Session.Open() if err != nil { - fmt.Println("error opening connection,", err) + log.Error("error opening connection,", err) return } - fmt.Println("Bot is now running...") + log.Debug("Bot is now running...") // Simple way to keep program running until CTRL-C is pressed. <-make(chan struct{}) diff --git a/server/bothandlers/gif.go b/server/bothandlers/gif.go index 43f28fc..381e29a 100644 --- a/server/bothandlers/gif.go +++ b/server/bothandlers/gif.go @@ -1,5 +1,7 @@ package bothandlers +/***** DEPRECATED *****/ + import ( "io/ioutil" "math/rand" diff --git a/server/bothandlers/sounds.go b/server/bothandlers/sounds.go index e092422..b58b90d 100644 --- a/server/bothandlers/sounds.go +++ b/server/bothandlers/sounds.go @@ -6,7 +6,6 @@ import ( "errors" "io" "io/ioutil" - "log" "os" "os/exec" "strconv" @@ -19,6 +18,7 @@ import ( "github.com/bwmarrin/discordgo" "github.com/cryptix/wav" "github.com/mgerb/go-discord-bot/server/config" + log "github.com/sirupsen/logrus" ) const ( @@ -61,7 +61,7 @@ func SoundsHandler(s *discordgo.Session, m *discordgo.MessageCreate) { c, err := s.State.Channel(m.ChannelID) if err != nil { // Could not find channel. - log.Println("Unable to find channel.") + log.Error("Unable to find channel.") return } @@ -71,7 +71,7 @@ func SoundsHandler(s *discordgo.Session, m *discordgo.MessageCreate) { // Find the guild for that channel. newGuild, err := s.State.Guild(c.GuildID) if err != nil { - log.Println(err) + log.Error(err) return } @@ -138,14 +138,14 @@ func (conn *audioConnection) summon(m *discordgo.MessageCreate) { c, err := conn.session.State.Channel(m.ChannelID) if err != nil { // Could not find channel. - log.Println("User channel not found.") + log.Error("User channel not found.") return } // Find the guild for that channel. g, err := conn.session.State.Guild(c.GuildID) if err != nil { - log.Println(err) + log.Error(err) return } @@ -156,7 +156,7 @@ func (conn *audioConnection) summon(m *discordgo.MessageCreate) { conn.voiceConnection, err = conn.session.ChannelVoiceJoin(g.ID, vs.ChannelID, false, false) if err != nil { - log.Println(err) + log.Error(err) } // set the current channel @@ -184,7 +184,7 @@ func (conn *audioConnection) playAudio(soundName string, m *discordgo.MessageCre err := conn.loadFile(soundName) if err != nil { - log.Println(err) + log.Error(err) return } } @@ -224,7 +224,7 @@ func (conn *audioConnection) loadFile(fileName string) error { return errors.New("File not found") } - log.Println("Loading file: " + fname + fextension) + log.Debug("Loading file: " + fname + fextension) // use ffmpeg to convert file into a format we can use cmd := exec.Command("ffmpeg", "-i", config.Config.SoundsPath+fname+fextension, "-f", "s16le", "-ar", strconv.Itoa(frameRate), "-ac", strconv.Itoa(channels), "pipe:1") @@ -353,14 +353,14 @@ loop: if !ok { speakers[opusChannel.SSRC], err = gopus.NewDecoder(frameRate, 1) if err != nil { - log.Println("error creating opus decoder", err) + log.Error("error creating opus decoder", err) continue } } opusChannel.PCM, err = speakers[opusChannel.SSRC].Decode(opusChannel.Opus, frameSize, false) if err != nil { - log.Println("Error decoding opus data", err) + log.Error("Error decoding opus data", err) continue } @@ -424,6 +424,6 @@ func (conn *audioConnection) toggleSoundPlayingLock(playing bool) { func checkErr(err error) { if err != nil { - log.Println(err) + log.Error(err) } } diff --git a/server/config/config.go b/server/config/config.go index 649c99e..c1d70db 100644 --- a/server/config/config.go +++ b/server/config/config.go @@ -3,9 +3,8 @@ package config import ( "encoding/json" "flag" + log "github.com/sirupsen/logrus" "io/ioutil" - "log" - "os" ) // Variables used for command line parameters @@ -30,52 +29,45 @@ type configFile struct { type configFlags struct { Prod bool - TLS bool } // Init - func Init() { - parseConfig() parseFlags() - } func parseConfig() { - log.Println("Reading config file...") + log.Debug("Reading config file...") file, e := ioutil.ReadFile("./config.json") if e != nil { - log.Printf("File error: %v\n", e) - os.Exit(1) + log.Fatal("File error: %v\n", e) } - log.Printf("%s\n", string(file)) + log.Debug("%s\n", string(file)) err := json.Unmarshal(file, &Config) if err != nil { - log.Println(err) + log.Error(err) } } func parseFlags() { Flags.Prod = false - Flags.TLS = false prod := flag.Bool("p", false, "Run in production") - tls := flag.Bool("tls", false, "Use TLS") flag.Parse() Flags.Prod = *prod - Flags.TLS = *tls - if *prod { - log.Println("Running in production mode") + if Flags.Prod { + log.Warn("Running in production mode") } } diff --git a/server/response/response.go b/server/response/response.go deleted file mode 100644 index 53c3abc..0000000 --- a/server/response/response.go +++ /dev/null @@ -1,32 +0,0 @@ -package response - -import ( - "encoding/json" - "net/http" -) - -var ( - DefaultUnauthorized = []byte("Unauthorized.") - DefaultInternalError = []byte("Internal error.") -) - -// JSON - marshals the provided interface and returns JSON to client -func JSON(w http.ResponseWriter, content interface{}) { - - output, err := json.Marshal(content) - - if err != nil { - ERR(w, http.StatusInternalServerError, []byte("Internal error.")) - return - } - - w.Header().Set("content-type", "application/json") - w.WriteHeader(http.StatusOK) - w.Write(output) -} - -// ERR - send error response -func ERR(w http.ResponseWriter, status int, content []byte) { - w.WriteHeader(status) - w.Write(content) -} diff --git a/server/webserver/handlers/downloader.go b/server/webserver/handlers/downloader.go index 4fe12d6..84c55e6 100644 --- a/server/webserver/handlers/downloader.go +++ b/server/webserver/handlers/downloader.go @@ -2,19 +2,18 @@ package handlers import ( "bytes" - "log" - "net/http" "os" "os/exec" "regexp" - "github.com/mgerb/chi_auth_server/response" + "github.com/gin-gonic/gin" + log "github.com/sirupsen/logrus" ) // Downloader - -func Downloader(w http.ResponseWriter, r *http.Request) { - url := r.FormValue("url") - fileType := r.FormValue("fileType") +func Downloader(c *gin.Context) { + url := c.Query("url") + fileType := c.Query("fileType") // create youtube folder if it does not exist if _, err := os.Stat("youtube"); os.IsNotExist(err) { @@ -29,8 +28,8 @@ func Downloader(w http.ResponseWriter, r *http.Request) { err := titleCmd.Run() if err != nil { - log.Println(err) - response.ERR(w, http.StatusInternalServerError, response.DefaultInternalError) + log.Error(err) + c.JSON(400, err) return } @@ -40,7 +39,7 @@ func Downloader(w http.ResponseWriter, r *http.Request) { // remove all special characters from title cleanTitle := cleanseTitle(titleOut.String()) - log.Println(cleanTitle) + log.Debug(cleanTitle) cmd := exec.Command("youtube-dl", "-x", "--audio-format", "mp3", "-o", "./youtube/"+cleanTitle+".%(ext)s", url) @@ -50,13 +49,13 @@ func Downloader(w http.ResponseWriter, r *http.Request) { err = cmd.Run() if err != nil { - log.Println(out.String()) - log.Println(err) - response.ERR(w, http.StatusInternalServerError, response.DefaultInternalError) + log.Error(out.String()) + log.Error(err) + c.JSON(400, err) return } - response.JSON(w, map[string]interface{}{"fileName": cleanTitle + "." + fileType}) + c.JSON(200, map[string]interface{}{"fileName": cleanTitle + "." + fileType}) } func cleanseTitle(title string) string { @@ -64,7 +63,7 @@ func cleanseTitle(title string) string { // Make a Regex to say we only want reg, err := regexp.Compile("[^a-zA-Z0-9]+") if err != nil { - log.Fatal(err) + log.Error(err) } return reg.ReplaceAllString(title, "") diff --git a/server/webserver/handlers/soundlist.go b/server/webserver/handlers/soundlist.go index 130637f..e8fad8e 100644 --- a/server/webserver/handlers/soundlist.go +++ b/server/webserver/handlers/soundlist.go @@ -2,13 +2,13 @@ package handlers import ( "io/ioutil" - "log" "strings" "net/http" - "github.com/mgerb/chi_auth_server/response" + "github.com/gin-gonic/gin" "github.com/mgerb/go-discord-bot/server/config" + log "github.com/sirupsen/logrus" ) var soundList []sound @@ -20,17 +20,17 @@ type sound struct { } // SoundList - -func SoundList(w http.ResponseWriter, r *http.Request) { +func SoundList(c *gin.Context) { if len(soundList) < 1 { err := PopulateSoundList() if err != nil { - response.ERR(w, http.StatusInternalServerError, []byte(response.DefaultInternalError)) + c.JSON(http.StatusInternalServerError, err) return } } - response.JSON(w, soundList) + c.JSON(200, soundList) } // PopulateSoundList - @@ -61,15 +61,15 @@ func PopulateSoundList() error { } // ClipList - -func ClipList(w http.ResponseWriter, r *http.Request) { +func ClipList(c *gin.Context) { clipList := []sound{} files, err := ioutil.ReadDir(config.Config.ClipsPath) if err != nil { - log.Println(err) - response.ERR(w, 500, response.DefaultInternalError) + log.Error(err) + c.JSON(http.StatusInternalServerError, err) return } @@ -85,5 +85,5 @@ func ClipList(w http.ResponseWriter, r *http.Request) { clipList = append(clipList, listItem) } - response.JSON(w, clipList) + c.JSON(200, clipList) } diff --git a/server/webserver/handlers/upload.go b/server/webserver/handlers/upload.go index a259c35..ca5b5d2 100644 --- a/server/webserver/handlers/upload.go +++ b/server/webserver/handlers/upload.go @@ -1,67 +1,54 @@ package handlers import ( - "io" "os" "strings" "net/http" - "github.com/mgerb/chi_auth_server/response" + "github.com/gin-gonic/gin" "github.com/mgerb/go-discord-bot/server/config" + log "github.com/sirupsen/logrus" ) // FileUpload -func FileUpload(w http.ResponseWriter, r *http.Request) { +func FileUpload(c *gin.Context) { - password := r.FormValue("password") + password := c.PostForm("password") if string(password) != config.Config.UploadPassword { - response.ERR(w, http.StatusInternalServerError, []byte("Invalid password.")) + c.JSON(http.StatusInternalServerError, "Invalid password.") return } - file, header, err := r.FormFile("file") + file, err := c.FormFile("file") if err != nil { - response.ERR(w, http.StatusInternalServerError, []byte("Error reading file.")) + log.Error(err) + c.JSON(http.StatusInternalServerError, "Error reading file.") return } - defer file.Close() - - src, err := header.Open() - if err != nil { - response.ERR(w, http.StatusInternalServerError, []byte("Error opening file.")) - return - } - - defer src.Close() - // create uploads folder if it does not exist if _, err := os.Stat(config.Config.SoundsPath); os.IsNotExist(err) { os.Mkdir(config.Config.SoundsPath, os.ModePerm) } // convert file name to lower case and trim spaces - header.Filename = strings.ToLower(header.Filename) - header.Filename = strings.Replace(header.Filename, " ", "", -1) + file.Filename = strings.ToLower(file.Filename) + file.Filename = strings.Replace(file.Filename, " ", "", -1) // check if file already exists - if _, err := os.Stat(config.Config.SoundsPath + header.Filename); err == nil { - response.ERR(w, http.StatusInternalServerError, []byte("File already exists.")) + if _, err := os.Stat(config.Config.SoundsPath + file.Filename); err == nil { + c.JSON(http.StatusInternalServerError, "File already exists.") return } - dst, err := os.Create(config.Config.SoundsPath + header.Filename) + err = c.SaveUploadedFile(file, config.Config.SoundsPath+file.Filename) + log.Debug("Saving file", config.Config.SoundsPath+file.Filename) + if err != nil { - response.ERR(w, http.StatusInternalServerError, []byte("Error creating file.")) - return - } - - defer dst.Close() - - if _, err = io.Copy(dst, src); err != nil { - response.ERR(w, http.StatusInternalServerError, []byte("Error writing file.")) + log.Error(err) + c.JSON(http.StatusInternalServerError, "Error creating file.") return } @@ -69,9 +56,10 @@ func FileUpload(w http.ResponseWriter, r *http.Request) { err = PopulateSoundList() if err != nil { - response.ERR(w, http.StatusInternalServerError, []byte("Error populating sound list.")) + log.Error(err) + c.JSON(http.StatusInternalServerError, "Error populating sound list.") return } - response.JSON(w, []byte("Success")) + c.JSON(200, "Success") } diff --git a/server/webserver/pubg/pubg.go b/server/webserver/pubg/pubg.go index 31edd7a..a42d9b0 100644 --- a/server/webserver/pubg/pubg.go +++ b/server/webserver/pubg/pubg.go @@ -1,13 +1,12 @@ package pubg import ( - "log" - "net/http" "sync" "time" - "github.com/mgerb/chi_auth_server/response" + "github.com/gin-gonic/gin" pubgClient "github.com/mgerb/go-pubg" + log "github.com/sirupsen/logrus" ) var ( @@ -21,7 +20,7 @@ func Start(key string, players []string) { apiKey = key - log.Println("Gathering pubg data...") + log.Debug("Gathering pubg data...") go fetchStats(players) } @@ -41,7 +40,7 @@ func fetchStats(players []string) { newStats, err := api.GetPlayer(player) if err != nil { - log.Println(err) + log.Error(err) continue } @@ -58,6 +57,6 @@ func fetchStats(players []string) { } // Handler - returns the pubg stats -func Handler(w http.ResponseWriter, r *http.Request) { - response.JSON(w, stats) +func Handler(c *gin.Context) { + c.JSON(200, stats) } diff --git a/server/webserver/server.go b/server/webserver/server.go index aab0cab..90c5d6d 100644 --- a/server/webserver/server.go +++ b/server/webserver/server.go @@ -1,53 +1,32 @@ package webserver import ( - "log" - "net/http" - "os" - "path/filepath" - "strings" - - "golang.org/x/crypto/acme/autocert" - - "github.com/go-chi/chi" - "github.com/go-chi/chi/middleware" + "github.com/gin-gonic/gin" "github.com/mgerb/go-discord-bot/server/config" "github.com/mgerb/go-discord-bot/server/webserver/handlers" "github.com/mgerb/go-discord-bot/server/webserver/pubg" ) -func getRouter() *chi.Mux { +func getRouter() *gin.Engine { + router := gin.Default() - r := chi.NewRouter() + router.Static("/static", "./dist/static") + router.Static("/public/sounds", config.Config.SoundsPath) + router.Static("/public/youtube", "./youtube") + router.Static("/public/clips", config.Config.ClipsPath) - r.Use(middleware.RequestID) - r.Use(middleware.DefaultCompress) - - if !config.Flags.Prod { - r.Use(middleware.Logger) - } - - workDir, _ := os.Getwd() - - FileServer(r, "/static", http.Dir(filepath.Join(workDir, "./dist/static"))) - FileServer(r, "/public/sounds", http.Dir(filepath.Join(workDir, config.Config.SoundsPath))) - FileServer(r, "/public/youtube", http.Dir(filepath.Join(workDir, "./youtube"))) - FileServer(r, "/public/clips", http.Dir(filepath.Join(workDir, config.Config.ClipsPath))) - - r.NotFound(func(w http.ResponseWriter, r *http.Request) { - http.ServeFile(w, r, "./dist/index.html") + router.NoRoute(func(c *gin.Context) { + c.File("./dist/index.html") }) - r.Route("/api", func(r chi.Router) { - // configure api end points - r.Get("/soundlist", handlers.SoundList) - r.Get("/cliplist", handlers.ClipList) - r.Put("/upload", handlers.FileUpload) - r.Get("/ytdownloader", handlers.Downloader) - r.Get("/stats/pubg", pubg.Handler) - }) + api := router.Group("/api") + api.GET("/stats/pubg", pubg.Handler) + api.GET("/ytdownloader", handlers.Downloader) + api.GET("/soundlist", handlers.SoundList) + api.GET("/cliplist", handlers.ClipList) + api.POST("/upload", handlers.FileUpload) - return r + return router } // Start - @@ -59,49 +38,5 @@ func Start() { } router := getRouter() - - if config.Flags.TLS { - - // start server on port 80 to redirect - go http.ListenAndServe(":80", http.HandlerFunc(redirect)) - - // start TLS server - log.Fatal(http.Serve(autocert.NewListener(), router)) - - } else { - - // start basic server - http.ListenAndServe(config.Config.ServerAddr, router) - } -} - -// FileServer conveniently sets up a http.FileServer handler to serve -// static files from a http.FileSystem. -func FileServer(r chi.Router, path string, root http.FileSystem) { - if strings.ContainsAny(path, "{}*") { - panic("FileServer does not permit URL parameters.") - } - - fs := http.StripPrefix(path, http.FileServer(root)) - - if path != "/" && path[len(path)-1] != '/' { - r.Get(path, http.RedirectHandler(path+"/", 301).ServeHTTP) - path += "/" - } - path += "*" - - r.Get(path, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - fs.ServeHTTP(w, r) - })) -} - -// redirect to https -func redirect(w http.ResponseWriter, req *http.Request) { - // remove/add not default ports from req.Host - target := "https://" + req.Host + req.URL.Path - if len(req.URL.RawQuery) > 0 { - target += "?" + req.URL.RawQuery - } - - http.Redirect(w, req, target, http.StatusTemporaryRedirect) + router.Run(config.Config.ServerAddr) }