main.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  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. stash = append(stash, file.Name())
  114. }
  115. c.HTML(200, "stash.tmpl", gin.H{
  116. "stash": stash,
  117. })
  118. })
  119. r.GET("/stash/edit/:name", func(c *gin.Context) {
  120. name := c.Param("name")
  121. log.WithFields(log.Fields{
  122. "name": name,
  123. }).Info("Restore session?")
  124. if strings.HasSuffix(name, ".md") {
  125. name = name[0 : len(name)-3]
  126. }
  127. path := SlidePath(name)
  128. session := sessions.Default(c)
  129. session.Set("name", path)
  130. session.Save()
  131. c.HTML(200, "index.tmpl", gin.H{
  132. "pubTo": path,
  133. })
  134. })
  135. r.GET("/published/slides/:name", func(c *gin.Context) {
  136. name := c.Param("name")
  137. log.WithFields(log.Fields{
  138. "name": name,
  139. }).Info("Published")
  140. if strings.HasSuffix(name, ".md") {
  141. name = name[0 : len(name)-3]
  142. }
  143. path := SlidePath(name)
  144. session := sessions.Default(c)
  145. session.Set("name", path)
  146. session.Save()
  147. c.HTML(200, "slides.tmpl", gin.H{
  148. "pubTo": path,
  149. })
  150. })
  151. return r
  152. }
  153. func main() {
  154. r := NewApp()
  155. port := "8080"
  156. if len(os.Args) > 1 {
  157. port = os.Args[1]
  158. } else {
  159. envPort := os.Getenv("PORT")
  160. if len(envPort) > 0 {
  161. port = envPort
  162. }
  163. }
  164. log.Info("Started http://0.0.0.0:8080")
  165. r.Run(fmt.Sprintf(":%s", port))
  166. }