main.go 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. package main
  2. import (
  3. "errors"
  4. "fmt"
  5. "io/ioutil"
  6. "os"
  7. "strings"
  8. log "github.com/Sirupsen/logrus"
  9. haikunator "github.com/atrox/haikunatorgo"
  10. "github.com/gin-contrib/sessions"
  11. "github.com/gin-gonic/gin"
  12. "github.com/msoedov/hacker-slides/auth"
  13. "github.com/msoedov/hacker-slides/files"
  14. )
  15. const sessionHeader = "slide-session"
  16. func SlidePath(name string) string {
  17. return fmt.Sprintf("slides/%s.md", name)
  18. }
  19. func NewApp() *gin.Engine {
  20. r := gin.Default()
  21. store := sessions.NewCookieStore([]byte("secret"))
  22. r.Use(sessions.Sessions(sessionHeader, store))
  23. r.Use(auth.BasicAuth())
  24. r.LoadHTMLGlob("templates/*.tmpl")
  25. r.Static("/static", "./static")
  26. r.Static("/images", "./slides/images")
  27. r.GET("/", func(c *gin.Context) {
  28. isNew := c.Query("new")
  29. latest := files.LatestFileIn("slides")
  30. log.WithFields(log.Fields{
  31. "name": latest,
  32. "isNew": isNew,
  33. }).Info("Restoring latest point")
  34. var path, name string
  35. if latest == "" || isNew != "" {
  36. haikunator := haikunator.New()
  37. haikunator.TokenLength = 0
  38. name = haikunator.Haikunate()
  39. } else {
  40. name = strings.Replace(latest, ".md", "", 1)
  41. }
  42. path = SlidePath(name)
  43. log.WithFields(log.Fields{
  44. "path": path,
  45. }).Info("A new session")
  46. session := sessions.Default(c)
  47. session.Set("name", path)
  48. session.Save()
  49. c.Writer.Header().Set("Location", fmt.Sprintf("/stash/edit/%s", name))
  50. c.HTML(302, "index.tmpl", gin.H{
  51. "pubTo": path,
  52. })
  53. })
  54. mustHaveSession := func(c *gin.Context) (string, error) {
  55. session := sessions.Default(c)
  56. val := session.Get("name")
  57. emptySession := errors.New("Emtpy session")
  58. if val == nil {
  59. c.String(400, "No context")
  60. return "", emptySession
  61. }
  62. log.WithFields(log.Fields{
  63. "path": val,
  64. }).Info("Got session")
  65. path, ok := val.(string)
  66. if !ok {
  67. c.String(400, "No context")
  68. return "", emptySession
  69. }
  70. return path, nil
  71. }
  72. r.GET("/slides.md", func(c *gin.Context) {
  73. path, err := mustHaveSession(c)
  74. if err != nil {
  75. return
  76. }
  77. if _, err := os.Stat(path); err != nil {
  78. // copy sample markdown file to the path
  79. body, err := ioutil.ReadFile("initial-slides.md")
  80. if err != nil {
  81. panic(err)
  82. }
  83. ioutil.WriteFile(path, body, 0644)
  84. c.String(200, string(body))
  85. return
  86. }
  87. body, err := ioutil.ReadFile(path)
  88. if err != nil {
  89. panic(err)
  90. }
  91. c.String(200, string(body))
  92. })
  93. r.PUT("/slides.md", func(c *gin.Context) {
  94. path, err := mustHaveSession(c)
  95. if err != nil {
  96. return
  97. }
  98. body, _ := ioutil.ReadAll(c.Request.Body)
  99. ioutil.WriteFile(path, body, 0644)
  100. log.WithFields(log.Fields{
  101. "size": len(body),
  102. "file": path,
  103. }).Info("Wrote to file")
  104. c.String(200, "")
  105. })
  106. r.GET("/stash", func(c *gin.Context) {
  107. files, err := ioutil.ReadDir("slides")
  108. if err != nil {
  109. log.Fatal(err)
  110. }
  111. var stash []string
  112. for _, file := range files {
  113. if file.IsDir() {
  114. continue
  115. }
  116. stash = append(stash, file.Name())
  117. }
  118. c.HTML(200, "stash.tmpl", gin.H{
  119. "stash": stash,
  120. })
  121. })
  122. r.GET("/stash/edit/:name", func(c *gin.Context) {
  123. name := c.Param("name")
  124. log.WithFields(log.Fields{
  125. "name": name,
  126. }).Info("Restore session?")
  127. if strings.HasSuffix(name, ".md") {
  128. name = name[0 : len(name)-3]
  129. }
  130. path := SlidePath(name)
  131. session := sessions.Default(c)
  132. session.Set("name", path)
  133. session.Save()
  134. c.HTML(200, "index.tmpl", gin.H{
  135. "pubTo": path,
  136. })
  137. })
  138. r.GET("/published/slides/:name", func(c *gin.Context) {
  139. name := c.Param("name")
  140. log.WithFields(log.Fields{
  141. "name": name,
  142. }).Info("Published")
  143. if strings.HasSuffix(name, ".md") {
  144. name = name[0 : len(name)-3]
  145. }
  146. path := SlidePath(name)
  147. session := sessions.Default(c)
  148. session.Set("name", path)
  149. session.Save()
  150. c.HTML(200, "slides.tmpl", gin.H{
  151. "pubTo": path,
  152. })
  153. })
  154. return r
  155. }
  156. func main() {
  157. r := NewApp()
  158. port := "8080"
  159. if len(os.Args) > 1 {
  160. port = os.Args[1]
  161. } else {
  162. envPort := os.Getenv("PORT")
  163. if len(envPort) > 0 {
  164. port = envPort
  165. }
  166. }
  167. log.Info("Started http://0.0.0.0:8080")
  168. r.Run(fmt.Sprintf(":%s", port))
  169. }