main.go 3.9 KB

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