|
|
|
/*
|
|
|
|
* Copyright © 2018-2019 Musing Studio LLC.
|
|
|
|
*
|
|
|
|
* This file is part of WriteFreely.
|
|
|
|
*
|
|
|
|
* WriteFreely is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU Affero General Public License, included
|
|
|
|
* in the LICENSE file in this source code package.
|
|
|
|
*/
|
|
|
|
|
|
|
|
package writefreely
|
|
|
|
|
|
|
|
import (
|
|
|
|
"archive/zip"
|
|
|
|
"bytes"
|
|
|
|
"encoding/csv"
|
|
|
|
"strings"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/writeas/web-core/log"
|
|
|
|
)
|
|
|
|
|
|
|
|
func exportPostsCSV(hostName string, u *User, posts *[]PublicPost) []byte {
|
|
|
|
var b bytes.Buffer
|
|
|
|
|
|
|
|
r := [][]string{
|
|
|
|
{"id", "slug", "blog", "url", "created", "title", "body"},
|
|
|
|
}
|
|
|
|
for _, p := range *posts {
|
|
|
|
var blog string
|
|
|
|
if p.Collection != nil {
|
|
|
|
blog = p.Collection.Alias
|
|
|
|
p.Collection.hostName = hostName
|
|
|
|
}
|
|
|
|
f := []string{p.ID, p.Slug.String, blog, p.CanonicalURL(hostName), p.Created8601(), p.Title.String, strings.Replace(p.Content, "\n", "\\n", -1)}
|
|
|
|
r = append(r, f)
|
|
|
|
}
|
|
|
|
|
|
|
|
w := csv.NewWriter(&b)
|
|
|
|
w.WriteAll(r) // calls Flush internally
|
|
|
|
if err := w.Error(); err != nil {
|
|
|
|
log.Info("error writing csv: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return b.Bytes()
|
|
|
|
}
|
|
|
|
|
|
|
|
type exportedTxt struct {
|
|
|
|
Name, Title, Body string
|
|
|
|
|
|
|
|
Mod time.Time
|
|
|
|
}
|
|
|
|
|
|
|
|
func exportPostsZip(u *User, posts *[]PublicPost) []byte {
|
|
|
|
// Create a buffer to write our archive to.
|
|
|
|
b := new(bytes.Buffer)
|
|
|
|
|
|
|
|
// Create a new zip archive.
|
|
|
|
w := zip.NewWriter(b)
|
|
|
|
|
|
|
|
// Add some files to the archive.
|
|
|
|
var filename string
|
|
|
|
files := []exportedTxt{}
|
|
|
|
for _, p := range *posts {
|
|
|
|
filename = ""
|
|
|
|
if p.Collection != nil {
|
|
|
|
filename += p.Collection.Alias + "/"
|
|
|
|
}
|
|
|
|
if p.Slug.String != "" {
|
|
|
|
filename += p.Slug.String + "_"
|
|
|
|
}
|
|
|
|
filename += p.ID + ".txt"
|
|
|
|
files = append(files, exportedTxt{filename, p.Title.String, p.Content, p.Created})
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, file := range files {
|
|
|
|
head := &zip.FileHeader{Name: file.Name}
|
|
|
|
head.SetModTime(file.Mod)
|
|
|
|
f, err := w.CreateHeader(head)
|
|
|
|
if err != nil {
|
|
|
|
log.Error("export zip header: %v", err)
|
|
|
|
}
|
|
|
|
var fullPost string
|
|
|
|
if file.Title != "" {
|
|
|
|
fullPost = "# " + file.Title + "\n\n"
|
|
|
|
}
|
|
|
|
fullPost += file.Body
|
|
|
|
_, err = f.Write([]byte(fullPost))
|
|
|
|
if err != nil {
|
|
|
|
log.Error("export zip write: %v", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Make sure to check the error on Close.
|
|
|
|
err := w.Close()
|
|
|
|
if err != nil {
|
|
|
|
log.Error("export zip close: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return b.Bytes()
|
|
|
|
}
|
|
|
|
|
|
|
|
func compileFullExport(app *App, u *User) *ExportUser {
|
|
|
|
exportUser := &ExportUser{
|
|
|
|
User: u,
|
|
|
|
}
|
|
|
|
|
|
|
|
colls, err := app.db.GetCollections(u, app.cfg.App.Host)
|
|
|
|
if err != nil {
|
|
|
|
log.Error("unable to fetch collections: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
posts, err := app.db.GetAnonymousPosts(u, 0)
|
|
|
|
if err != nil {
|
|
|
|
log.Error("unable to fetch anon posts: %v", err)
|
|
|
|
}
|
|
|
|
exportUser.AnonymousPosts = *posts
|
|
|
|
|
|
|
|
var collObjs []CollectionObj
|
|
|
|
for _, c := range *colls {
|
|
|
|
co := &CollectionObj{Collection: c}
|
|
|
|
co.Posts, err = app.db.GetPosts(app.cfg, &c, 0, true, false, true, "")
|
|
|
|
if err != nil {
|
|
|
|
log.Error("unable to get collection posts: %v", err)
|
|
|
|
}
|
|
|
|
app.db.GetPostsCount(co, true)
|
|
|
|
collObjs = append(collObjs, *co)
|
|
|
|
}
|
|
|
|
exportUser.Collections = &collObjs
|
|
|
|
|
|
|
|
return exportUser
|
|
|
|
}
|