diff --git a/Makefile b/Makefile index 3810c7a0..c3a90140 100644 --- a/Makefile +++ b/Makefile @@ -11,7 +11,7 @@ up: docker-compose up -d --force-recreate --remove-orphans .PHONY: dev -dev: calc-www +dev: install calc-www server diff --git a/cmd/calc-www/main.go b/cmd/calc-www/main.go index 42dad159..860994e4 100644 --- a/cmd/calc-www/main.go +++ b/cmd/calc-www/main.go @@ -1,26 +1,21 @@ package main import ( - "fmt" "net/http" "os" - "strconv" + "time" "github.com/gin-gonic/gin" - "github.com/tpyolang/tpyo-cli" + "github.com/go-chi/chi" + "github.com/go-chi/chi/middleware" + "github.com/go-chi/render" + "github.com/gobuffalo/packr" "github.com/urfave/cli" "ultre.me/calcbiz" - "ultre.me/calcbiz/pkg/crew" "ultre.me/calcbiz/pkg/dashboard" "ultre.me/calcbiz/pkg/log" - "ultre.me/calcbiz/pkg/numberinfo" - "ultre.me/calcbiz/pkg/random" "ultre.me/calcbiz/pkg/soundcloud" - "ultre.me/calcbiz/pkg/spreadshirt" - "ultre.me/kryptos" - "ultre.me/moi-j-aime-generator" - "ultre.me/recettator" ) func main() { @@ -76,264 +71,282 @@ func main() { } func server(c *cli.Context) error { - r := gin.Default() + r := chi.NewRouter() + //r.Use(middleware.RequestID) + //r.Use(middleware.RealIP) + r.Use(middleware.Logger) + r.Use(middleware.Recoverer) + //r.Use(middleware.URLFormat) + r.Use(middleware.Timeout(5 * time.Second)) - // ping - pong := func(c *gin.Context) { - c.JSON(http.StatusOK, gin.H{ - "result": "pong", - }) - } - r.GET("/api/ping", pong) - r.POST("/api/ping", pong) - r.PUT("/api/ping", pong) - r.PATCH("/api/ping", pong) - r.DELETE("/api/ping", pong) - - soundcloud := calcsoundcloud.New(c.String("soundcloud-client-id"), uint64(c.Int("soundcloud-user-id"))) - dashboard := calcdashboard.New() - dashboard.SetSoundCloud(&soundcloud) + r.Route("/api", func(r chi.Router) { + r.Use(render.SetContentType(render.ContentTypeJSON)) - // dashboard - r.GET("/api/dashboard/random", func(c *gin.Context) { - dashboard, err := dashboard.Random() - if err != nil { - c.JSON(http.StatusNotFound, gin.H{ - "error": err, - }) - } else { - c.JSON(http.StatusOK, gin.H{ - "result": dashboard, - }) + // ping + pong := func(w http.ResponseWriter, r *http.Request) { + w.Write([]byte(`{"result":"pong"}`)) } - }) + r.Get("/ping", pong) + r.Post("/ping", pong) + r.Options("/ping", pong) + r.Trace("/ping", pong) + r.Connect("/ping", pong) + r.Head("/ping", pong) + r.Put("/ping", pong) + r.Patch("/ping", pong) + r.Delete("/ping", pong) - // crew - r.GET("/api/crew", func(c *gin.Context) { - c.JSON(http.StatusOK, gin.H{ - "result": calccrew.CALC, - }) - }) - - // numberinfo - r.GET("/api/numberinfo/all/:number", func(c *gin.Context) { - number, err := strconv.ParseFloat(c.Param("number"), 64) - if err != nil { - c.JSON(http.StatusNotFound, gin.H{ - "error": fmt.Sprintf("Invalid number: %v (%v)", c.Param("number"), err), - }) - return - } + soundcloud := calcsoundcloud.New(c.String("soundcloud-client-id"), uint64(c.Int("soundcloud-user-id"))) + dashboard := calcdashboard.New() + dashboard.SetSoundCloud(&soundcloud) - info := calcnumberinfo.New(number).All() - c.JSON(http.StatusOK, gin.H{ - "result": info, + // dashboard + r.Get("/dashboard/random", func(w http.ResponseWriter, r *http.Request) { + dashboard, err := dashboard.Random() + if err != nil { + c.JSON(http.StatusNotFound, gin.H{ + "error": err, + }) + } else { + c.JSON(http.StatusOK, gin.H{ + "result": dashboard, + }) + } }) - }) - // recettator - r.GET("/api/recettator/json/:seed", func(c *gin.Context) { - seed, err := strconv.ParseInt(c.Param("seed"), 10, 64) - if err != nil { - c.JSON(http.StatusNotFound, gin.H{ - "error": fmt.Sprintf("Invalid seed: %v (%v)", c.Param("seed"), err), + /* + // crew + r.Get("/crew", func(w http.ResponseWriter, r *http.Request) { + c.JSON(http.StatusOK, gin.H{ + "result": calccrew.CALC, + }) }) - return - } - rctt := recettator.New(seed) - rctt.SetSettings(recettator.Settings{ - MainIngredients: 2, - SecondaryIngredients: 2, - Steps: 5, - }) + // numberinfo + r.Get("/numberinfo/all/:number", func(w http.ResponseWriter, r *http.Request) { + number, err := strconv.ParseFloat(c.Param("number"), 64) + if err != nil { + c.JSON(http.StatusNotFound, gin.H{ + "error": fmt.Sprintf("Invalid number: %v (%v)", c.Param("number"), err), + }) + return + } - output := rctt.ToMap() + info := calcnumberinfo.New(number).All() + c.JSON(http.StatusOK, gin.H{ + "result": info, + }) + }) - c.JSON(http.StatusOK, gin.H{ - "result": output, - }) - }) + // recettator + r.Get("/recettator/json/:seed", func(w http.ResponseWriter, r *http.Request) { + seed, err := strconv.ParseInt(c.Param("seed"), 10, 64) + if err != nil { + c.JSON(http.StatusNotFound, gin.H{ + "error": fmt.Sprintf("Invalid seed: %v (%v)", c.Param("seed"), err), + }) + return + } - // moijaime - r.GET("/api/moijaime", func(c *gin.Context) { - phrases := []string{} - for i := 0; i < 20; i++ { - phrases = append(phrases, moijaime.Generate()) - } - c.JSON(http.StatusOK, gin.H{ - "result": phrases, - }) - }) + rctt := recettator.New(seed) + rctt.SetSettings(recettator.Settings{ + MainIngredients: 2, + SecondaryIngredients: 2, + Steps: 5, + }) - // spreadshirt - r.GET("/api/spreadshirt/random", func(c *gin.Context) { - c.JSON(http.StatusOK, gin.H{ - "result": calcspreadshirt.GetRandomProduct(250, 250), - }) - }) - r.GET("/api/spreadshirt/all", func(c *gin.Context) { - c.JSON(http.StatusOK, gin.H{ - "result": calcspreadshirt.GetAllProducts(250, 250), - }) - }) + output := rctt.ToMap() - // kryptos - r.POST("/api/kryptos/encrypt", func(c *gin.Context) { - var data struct { - Message string - } - if err := c.BindJSON(&data); err == nil { - c.JSON(http.StatusOK, gin.H{ - "result": kryptos.Encrypt(data.Message), - }) - } else { - c.JSON(http.StatusNotFound, gin.H{ - "error": fmt.Sprintf("Invalid input: %v", err), - }) - } - }) - r.POST("/api/kryptos/decrypt", func(c *gin.Context) { - var data struct { - Message string - } - if err := c.BindJSON(&data); err == nil { - c.JSON(http.StatusOK, gin.H{ - "result": kryptos.Decrypt(data.Message), - }) - } else { - c.JSON(http.StatusNotFound, gin.H{ - "error": fmt.Sprintf("Invalid input: %v", err), + c.JSON(http.StatusOK, gin.H{ + "result": output, + }) }) - } - }) - // tpyo - r.POST("/api/tpyo/enocde", func(c *gin.Context) { - var data struct { - Message string - } - if err := c.BindJSON(&data); err == nil { - enedocr := tpyo.NewTpyo() - c.JSON(http.StatusOK, gin.H{ - "result": enedocr.Enocde(data.Message), - }) - } else { - c.JSON(http.StatusNotFound, gin.H{ - "error": fmt.Sprintf("Invalid input: %v", err), + // moijaime + r.Get("/moijaime", func(w http.ResponseWriter, r *http.Request) { + phrases := []string{} + for i := 0; i < 20; i++ { + phrases = append(phrases, moijaime.Generate()) + } + c.JSON(http.StatusOK, gin.H{ + "result": phrases, + }) }) - } - }) - - // random - r.GET("/api/random/wotd", func(c *gin.Context) { - c.JSON(http.StatusOK, gin.H{ - "result": calcrand.WOTD(), - }) - }) - r.GET("/api/random/alternate-logo", func(c *gin.Context) { - c.JSON(http.StatusOK, gin.H{ - "result": calcrand.AlternateLogo(), - }) - }) - // soundcloud - r.GET("/api/soundcloud/me", func(c *gin.Context) { - me, err := soundcloud.Me() - if err != nil { - log.Warnf("failed to get /api/soundcloud/me: %v", err) - c.JSON(http.StatusNotFound, gin.H{ - "error": soundcloud.EscapeString(fmt.Sprintf("%v", err)), - }) - } else { - c.JSON(http.StatusOK, gin.H{ - "result": me, + // spreadshirt + r.Get("/spreadshirt/random", func(w http.ResponseWriter, r *http.Request) { + c.JSON(http.StatusOK, gin.H{ + "result": calcspreadshirt.GetRandomProduct(250, 250), + }) }) - } - }) - r.GET("/api/soundcloud/playlists", func(c *gin.Context) { - playlists, err := soundcloud.Playlists() - if err != nil { - log.Warnf("failed to get /api/soundcloud/playlists: %v", err) - c.JSON(http.StatusNotFound, gin.H{ - "error": soundcloud.EscapeString(fmt.Sprintf("%v", err)), + r.Get("/spreadshirt/all", func(w http.ResponseWriter, r *http.Request) { + c.JSON(http.StatusOK, gin.H{ + "result": calcspreadshirt.GetAllProducts(250, 250), + }) }) - } else { - c.JSON(http.StatusOK, gin.H{ - "result": playlists, + + // kryptos + r.Post("/kryptos/encrypt", func(w http.ResponseWriter, r *http.Request) { + var data struct { + Message string + } + if err := c.BindJSON(&data); err == nil { + c.JSON(http.StatusOK, gin.H{ + "result": kryptos.Encrypt(data.Message), + }) + } else { + c.JSON(http.StatusNotFound, gin.H{ + "error": fmt.Sprintf("Invalid input: %v", err), + }) + } }) - } - }) - r.GET("/api/soundcloud/playlists/:id", func(c *gin.Context) { - playlistID, err := strconv.ParseUint(c.Param("id"), 10, 64) - if err != nil { - c.JSON(http.StatusNotFound, gin.H{ - "error": fmt.Sprintf("Invalid playlist id: %v", c.Param("id")), + r.Post("/kryptos/decrypt", func(w http.ResponseWriter, r *http.Request) { + var data struct { + Message string + } + if err := c.BindJSON(&data); err == nil { + c.JSON(http.StatusOK, gin.H{ + "result": kryptos.Decrypt(data.Message), + }) + } else { + c.JSON(http.StatusNotFound, gin.H{ + "error": fmt.Sprintf("Invalid input: %v", err), + }) + } }) - return - } - playlist, err := soundcloud.Playlist(playlistID) - if err != nil { - log.Warnf("failed to get /api/soundcloud/playlists/%d: %v", playlistID, err) - c.JSON(http.StatusNotFound, gin.H{ - "error": soundcloud.EscapeString(fmt.Sprintf("%v", err)), + // tpyo + r.Post("/tpyo/enocde", func(w http.ResponseWriter, r *http.Request) { + var data struct { + Message string + } + if err := c.BindJSON(&data); err == nil { + enedocr := tpyo.NewTpyo() + c.JSON(http.StatusOK, gin.H{ + "result": enedocr.Enocde(data.Message), + }) + } else { + c.JSON(http.StatusNotFound, gin.H{ + "error": fmt.Sprintf("Invalid input: %v", err), + }) + } }) - } else { - c.JSON(http.StatusOK, gin.H{ - "result": playlist, - }) - } - }) - r.GET("/api/soundcloud/tracks/:id", func(c *gin.Context) { - if c.Param("id") == "random" { - track, err := soundcloud.RandomTrack() - if err != nil { - log.Warnf("failed to get /api/soundcloud/tracks/random: %v", err) - c.JSON(http.StatusNotFound, gin.H{ - "error": soundcloud.EscapeString(fmt.Sprintf("%v", err)), + + // random + r.Get("/random/wotd", func(w http.ResponseWriter, r *http.Request) { + c.JSON(http.StatusOK, gin.H{ + "result": calcrand.WOTD(), }) - } else { + }) + r.Get("/random/alternate-logo", func(w http.ResponseWriter, r *http.Request) { c.JSON(http.StatusOK, gin.H{ - "result": track, + "result": calcrand.AlternateLogo(), }) - } - return - } - trackID, err := strconv.ParseUint(c.Param("id"), 10, 64) - if err != nil { - c.JSON(http.StatusNotFound, gin.H{ - "error": fmt.Sprintf("Invalid track id: %v", c.Param("id")), }) - return - } - track, err := soundcloud.Track(trackID) - if err != nil { - log.Warnf("failed to get /api/soundcloud/tracks/%d: %v", trackID, err) - c.JSON(http.StatusNotFound, gin.H{ - "error": soundcloud.EscapeString(fmt.Sprintf("%v", err)), + // soundcloud + r.Get("/soundcloud/me", func(w http.ResponseWriter, r *http.Request) { + me, err := soundcloud.Me() + if err != nil { + log.Warnf("failed to get /api/soundcloud/me: %v", err) + c.JSON(http.StatusNotFound, gin.H{ + "error": soundcloud.EscapeString(fmt.Sprintf("%v", err)), + }) + } else { + c.JSON(http.StatusOK, gin.H{ + "result": me, + }) + } }) - } else { - c.JSON(http.StatusOK, gin.H{ - "result": track, + r.Get("/soundcloud/playlists", func(w http.ResponseWriter, r *http.Request) { + playlists, err := soundcloud.Playlists() + if err != nil { + log.Warnf("failed to get /api/soundcloud/playlists: %v", err) + c.JSON(http.StatusNotFound, gin.H{ + "error": soundcloud.EscapeString(fmt.Sprintf("%v", err)), + }) + } else { + c.JSON(http.StatusOK, gin.H{ + "result": playlists, + }) + } }) - } - }) - r.GET("/api/soundcloud/tracks", func(c *gin.Context) { - tracks, err := soundcloud.Tracks() - if err != nil { - log.Warnf("failed to get /api/soundcloud/tracks: %v", err) - c.JSON(http.StatusNotFound, gin.H{ - "error": soundcloud.EscapeString(fmt.Sprintf("%v", err)), + r.Get("/soundcloud/playlists/:id", func(w http.ResponseWriter, r *http.Request) { + playlistID, err := strconv.ParseUint(c.Param("id"), 10, 64) + if err != nil { + c.JSON(http.StatusNotFound, gin.H{ + "error": fmt.Sprintf("Invalid playlist id: %v", c.Param("id")), + }) + return + } + + playlist, err := soundcloud.Playlist(playlistID) + if err != nil { + log.Warnf("failed to get /api/soundcloud/playlists/%d: %v", playlistID, err) + c.JSON(http.StatusNotFound, gin.H{ + "error": soundcloud.EscapeString(fmt.Sprintf("%v", err)), + }) + } else { + c.JSON(http.StatusOK, gin.H{ + "result": playlist, + }) + } }) - } else { - c.JSON(http.StatusOK, gin.H{ - "result": tracks, + r.Get("/soundcloud/tracks/:id", func(w http.ResponseWriter, r *http.Request) { + if c.Param("id") == "random" { + track, err := soundcloud.RandomTrack() + if err != nil { + log.Warnf("failed to get /api/soundcloud/tracks/random: %v", err) + c.JSON(http.StatusNotFound, gin.H{ + "error": soundcloud.EscapeString(fmt.Sprintf("%v", err)), + }) + } else { + c.JSON(http.StatusOK, gin.H{ + "result": track, + }) + } + return + } + trackID, err := strconv.ParseUint(c.Param("id"), 10, 64) + if err != nil { + c.JSON(http.StatusNotFound, gin.H{ + "error": fmt.Sprintf("Invalid track id: %v", c.Param("id")), + }) + return + } + + track, err := soundcloud.Track(trackID) + if err != nil { + log.Warnf("failed to get /api/soundcloud/tracks/%d: %v", trackID, err) + c.JSON(http.StatusNotFound, gin.H{ + "error": soundcloud.EscapeString(fmt.Sprintf("%v", err)), + }) + } else { + c.JSON(http.StatusOK, gin.H{ + "result": track, + }) + } }) - } + r.Get("/soundcloud/tracks", func(w http.ResponseWriter, r *http.Request) { + tracks, err := soundcloud.Tracks() + if err != nil { + log.Warnf("failed to get /api/soundcloud/tracks: %v", err) + c.JSON(http.StatusNotFound, gin.H{ + "error": soundcloud.EscapeString(fmt.Sprintf("%v", err)), + }) + } else { + c.JSON(http.StatusOK, gin.H{ + "result": tracks, + }) + } + }) + */ }) + // static files + box := packr.NewBox("./static") + r.Handle("/", http.FileServer(box)) + // FIXME: handle socket.io http.Handle("/", r) log.Debugf("Listening and serving HTTP on %s", c.String("bind-address")) diff --git a/go.mod b/go.mod index 47965775..6f2bf87f 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,9 @@ module ultre.me/calcbiz require ( github.com/gin-contrib/sse v0.0.0-20170109093832-22d885f9ecc7 // indirect github.com/gin-gonic/gin v1.3.0 + github.com/go-chi/chi v3.3.3+incompatible + github.com/go-chi/render v1.0.1 + github.com/gobuffalo/packr v1.13.7 github.com/golang/protobuf v1.2.0 // indirect github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 // indirect github.com/json-iterator/go v1.1.5 // indirect @@ -20,7 +23,6 @@ require ( github.com/urfave/cli v1.20.0 github.com/yanatan16/golang-soundcloud v0.0.0-20161013200625-a182dd459b66 golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519 // indirect - golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f // indirect golang.org/x/sys v0.0.0-20181023152157-44b849a8bc13 // indirect gopkg.in/go-playground/assert.v1 v1.2.1 // indirect gopkg.in/go-playground/validator.v8 v8.18.2 // indirect diff --git a/go.sum b/go.sum index a337a30b..230b48cb 100644 --- a/go.sum +++ b/go.sum @@ -10,6 +10,12 @@ github.com/gin-contrib/sse v0.0.0-20170109093832-22d885f9ecc7 h1:AzN37oI0cOS+cou github.com/gin-contrib/sse v0.0.0-20170109093832-22d885f9ecc7/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s= github.com/gin-gonic/gin v1.3.0 h1:kCmZyPklC0gVdL728E6Aj20uYBJV93nj/TkwBTKhFbs= github.com/gin-gonic/gin v1.3.0/go.mod h1:7cKuhb5qV2ggCFctp2fJQ+ErvciLZrIeoOSOm6mUr7Y= +github.com/go-chi/chi v3.3.3+incompatible h1:KHkmBEMNkwKuK4FdQL7N2wOeB9jnIx7jR5wsuSBEFI8= +github.com/go-chi/chi v3.3.3+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ= +github.com/go-chi/render v1.0.1 h1:4/5tis2cKaNdnv9zFLfXzcquC9HbeZgCnxGnKrltBS8= +github.com/go-chi/render v1.0.1/go.mod h1:pq4Rr7HbnsdaeHagklXub+p6Wd16Af5l9koip1OvJns= +github.com/gobuffalo/packr v1.13.7 h1:2uZgLd6b/W4yRBZV/ScaORxZLNGMHO0VCvqQNkKukNA= +github.com/gobuffalo/packr v1.13.7/go.mod h1:KkinLIn/n6+3tVXMwg6KkNvWwVsrRAz4ph+jgpk3Z24= github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/google/uuid v1.0.0 h1:b4Gk+7WdP/d3HZH8EJsZpvV7EtDOgaZLtnaNGIu1adA= @@ -20,6 +26,7 @@ github.com/huandu/xstrings v1.2.0 h1:yPeWdRnmynF7p+lLYz0H2tthW9lqhMJrQV/U7yy4wX0 github.com/huandu/xstrings v1.2.0/go.mod h1:DvyZB1rfVYsBIigL8HwpZgxHwXozlTgGqn63UyNX5k4= github.com/imdario/mergo v0.3.6 h1:xTNEAn+kxVO7dTZGu0CegyqKZmoWFI0rF8UxjlB2d28= github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/json-iterator/go v1.1.5 h1:gL2yXlmiIo4+t+y32d4WGwOjKGYcGOuyrg46vadswDE= github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/jtolds/gls v4.2.1+incompatible h1:fSuqC+Gmlu6l/ZYAoZzx2pyucC8Xza35fpRVWLVmUEE= @@ -39,6 +46,8 @@ github.com/moul/advanced-ssh-config v2.8.0+incompatible h1:TwBlAP+vrtYVW+cv+NJqG github.com/moul/advanced-ssh-config v2.8.0+incompatible/go.mod h1:R4jFrcdiyzi23qjl7fBUyk7zV3xoFv5S8ulBBsU2ufw= github.com/moul/numberinfo v0.0.0-20160903151149-753f372df509 h1:I9dq1rfaqOuM/cdoYtHeAK/nJxU2iRJAx9MPwHjoJic= github.com/moul/numberinfo v0.0.0-20160903151149-753f372df509/go.mod h1:9J61gswx3x7Sv1flRnwrSJv0jIksuHecefKXOnjMBpI= +github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/shazow/memoizer v0.0.0-20130904030615-74fc48eaeadc h1:uSeTSeeORwncCP2XKVZC3boAwbtXohDLo2MBan13xss= @@ -47,6 +56,8 @@ github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykE github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v0.0.0-20180222194500-ef6db91d284a h1:JSvGDIbmil4Ui/dDdFBExb7/cmkNjyX5F97oglmvCDo= github.com/smartystreets/goconvey v0.0.0-20180222194500-ef6db91d284a/go.mod h1:XDJAKZRPZ1CvBcN2aX5YOUTYGHki24fSF0Iv48Ibg0s= +github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/tpyolang/tpyo-cli v0.0.0-20160926074508-6ba04c3a8dec h1:UjKMIh4yA9dduh7CoE+c64egW0Bd3boiJNeFfcjLveM= @@ -59,6 +70,7 @@ github.com/yanatan16/golang-soundcloud v0.0.0-20161013200625-a182dd459b66 h1:Yb+ github.com/yanatan16/golang-soundcloud v0.0.0-20161013200625-a182dd459b66/go.mod h1:O8c2uEu4wGmxSTy5w3LOeBAsHBYJS9X/YK6vjZiZc2g= golang.org/x/crypto v0.0.0-20181015023909-0c41d7ab0a0e h1:IzypfodbhbnViNUO/MEh0FzCUooG97cIGfdggUrUSyU= golang.org/x/crypto v0.0.0-20181015023909-0c41d7ab0a0e/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/net v0.0.0-20180921000356-2f5d2388922f/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519 h1:x6rhz8Y9CjbgQkccRGmELH6K+LJj7tOoh3XWeC1yaQM= golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA= diff --git a/static/index.html b/static/index.html new file mode 100644 index 00000000..4e3dffe8 --- /dev/null +++ b/static/index.html @@ -0,0 +1 @@ +HELLO WORLD