A clean, Markdown-based publishing platform made for writers. Write together, and build a community. https://writefreely.org
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

133 lines
3.0 KiB

  1. /*
  2. * Copyright © 2018-2019 Musing Studio LLC.
  3. *
  4. * This file is part of WriteFreely.
  5. *
  6. * WriteFreely is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU Affero General Public License, included
  8. * in the LICENSE file in this source code package.
  9. */
  10. package writefreely
  11. import (
  12. "archive/zip"
  13. "bytes"
  14. "encoding/csv"
  15. "strings"
  16. "time"
  17. "github.com/writeas/web-core/log"
  18. )
  19. func exportPostsCSV(hostName string, u *User, posts *[]PublicPost) []byte {
  20. var b bytes.Buffer
  21. r := [][]string{
  22. {"id", "slug", "blog", "url", "created", "title", "body"},
  23. }
  24. for _, p := range *posts {
  25. var blog string
  26. if p.Collection != nil {
  27. blog = p.Collection.Alias
  28. p.Collection.hostName = hostName
  29. }
  30. f := []string{p.ID, p.Slug.String, blog, p.CanonicalURL(hostName), p.Created8601(), p.Title.String, strings.Replace(p.Content, "\n", "\\n", -1)}
  31. r = append(r, f)
  32. }
  33. w := csv.NewWriter(&b)
  34. w.WriteAll(r) // calls Flush internally
  35. if err := w.Error(); err != nil {
  36. log.Info("error writing csv: %v", err)
  37. }
  38. return b.Bytes()
  39. }
  40. type exportedTxt struct {
  41. Name, Title, Body string
  42. Mod time.Time
  43. }
  44. func exportPostsZip(u *User, posts *[]PublicPost) []byte {
  45. // Create a buffer to write our archive to.
  46. b := new(bytes.Buffer)
  47. // Create a new zip archive.
  48. w := zip.NewWriter(b)
  49. // Add some files to the archive.
  50. var filename string
  51. files := []exportedTxt{}
  52. for _, p := range *posts {
  53. filename = ""
  54. if p.Collection != nil {
  55. filename += p.Collection.Alias + "/"
  56. }
  57. if p.Slug.String != "" {
  58. filename += p.Slug.String + "_"
  59. }
  60. filename += p.ID + ".txt"
  61. files = append(files, exportedTxt{filename, p.Title.String, p.Content, p.Created})
  62. }
  63. for _, file := range files {
  64. head := &zip.FileHeader{Name: file.Name}
  65. head.SetModTime(file.Mod)
  66. f, err := w.CreateHeader(head)
  67. if err != nil {
  68. log.Error("export zip header: %v", err)
  69. }
  70. var fullPost string
  71. if file.Title != "" {
  72. fullPost = "# " + file.Title + "\n\n"
  73. }
  74. fullPost += file.Body
  75. _, err = f.Write([]byte(fullPost))
  76. if err != nil {
  77. log.Error("export zip write: %v", err)
  78. }
  79. }
  80. // Make sure to check the error on Close.
  81. err := w.Close()
  82. if err != nil {
  83. log.Error("export zip close: %v", err)
  84. }
  85. return b.Bytes()
  86. }
  87. func compileFullExport(app *App, u *User) *ExportUser {
  88. exportUser := &ExportUser{
  89. User: u,
  90. }
  91. colls, err := app.db.GetCollections(u, app.cfg.App.Host)
  92. if err != nil {
  93. log.Error("unable to fetch collections: %v", err)
  94. }
  95. posts, err := app.db.GetAnonymousPosts(u, 0)
  96. if err != nil {
  97. log.Error("unable to fetch anon posts: %v", err)
  98. }
  99. exportUser.AnonymousPosts = *posts
  100. var collObjs []CollectionObj
  101. for _, c := range *colls {
  102. co := &CollectionObj{Collection: c}
  103. co.Posts, err = app.db.GetPosts(app.cfg, &c, 0, true, false, true)
  104. if err != nil {
  105. log.Error("unable to get collection posts: %v", err)
  106. }
  107. app.db.GetPostsCount(co, true)
  108. collObjs = append(collObjs, *co)
  109. }
  110. exportUser.Collections = &collObjs
  111. return exportUser
  112. }