diff --git a/README.md b/README.md index 2cc523e..57c9542 100644 --- a/README.md +++ b/README.md @@ -1,27 +1,27 @@ # wf-migrate -[![GoDoc](https://godoc.org/github.com/writeas/wf-migrate?status.svg)](https://godoc.org/github.com/writeas/wf-migrate) +[![GoDoc](https://pkg.go.dev/badge/github.com/writefreely/wf-migrate?status.svg)](https://pkg.go.dev/github.com/writefreely/wf-migrate) wf-migrate provides helper functions and a command-line utility for migrating posts between [WriteFreely](https://writefreely.org) instances. ## Command-line Install the command-line utility with: ``` -go get github.com/writeas/wf-migrate/cmd/wfimport +go install github.com/writefreely/wf-migrate/cmd/wfimport ``` `wfimport` takes a username `-u`, optional WriteFreely instance hostname `-h`, and the filename of the JSON data you want to import. By default, `wfimport` publishes posts to [Write.as](https://write.as): ``` wfimport -u username exported-data.json ``` But you can also supply another WriteFreely instance to import to: ``` wfimport -u username -h pencil.writefree.ly exported-data.json ``` diff --git a/cmd/wfimport/main.go b/cmd/wfimport/main.go index 50c53d6..3b55788 100644 --- a/cmd/wfimport/main.go +++ b/cmd/wfimport/main.go @@ -1,152 +1,152 @@ package main import ( "encoding/json" "flag" "fmt" "github.com/howeyc/gopass" - "github.com/writeas/go-writeas" - "github.com/writeas/wf-migrate" + "github.com/writeas/go-writeas/v2" + "github.com/writefreely/wf-migrate" "io/ioutil" "os" ) func main() { // Get parameters u := flag.String("u", "", "WriteFreely username") host := flag.String("h", "write.as", "WriteFreely host") flag.Parse() // Validate parameters args := flag.Args() if *u == "" || len(args) == 0 { fmt.Fprintf(os.Stderr, "usage: wfimport -u username [-h example.com] file1\n") os.Exit(1) } fn := args[0] // Get password fmt.Print("Password: ") pass, err := gopass.GetPasswdMasked() if err != nil { fmt.Fprintf(os.Stderr, "error reading pass: %v\n", err) os.Exit(1) } // Validate password if len(pass) == 0 { fmt.Fprintf(os.Stderr, "Please enter your password.\n") os.Exit(1) } // Create Write.as client cl := writeas.NewClientWith(writeas.Config{ URL: "https://" + *host + "/api", }) // Log user in fmt.Printf("Logging in to %s...", *host) _, err = cl.LogIn(*u, string(pass)) if err != nil { fmt.Fprintf(os.Stderr, "error: %v\n", err) os.Exit(1) } fmt.Print("OK\n") defer func() { fmt.Print("Logging out...") cl.LogOut() fmt.Print("OK\n") }() // Get user's current collections fmt.Print("Getting your collections...") colls, err := cl.GetUserCollections() if err != nil { fmt.Fprintf(os.Stderr, "error %s: %v\n", fn, err) os.Exit(1) } fmt.Print("OK\n") userColls := map[string]bool{} for _, c := range *colls { userColls[c.Alias] = true } // Read file contents // TODO: validate fmt.Print("Reading file...") content, err := ioutil.ReadFile(fn) if err != nil { fmt.Fprintf(os.Stderr, "error %s: %v\n", fn, err) os.Exit(1) } fmt.Print("OK\n") imp := wfmigrate.Import{} fmt.Print("Parsing file...") err = json.Unmarshal(content, &imp) if err != nil { fmt.Fprintf(os.Stderr, "error %s: %v\n", fn, err) os.Exit(1) } fmt.Print("OK\n") fmtln("Read user %s export.", imp.User.Username) fmtln("Found %d collection(s).", len(imp.Collections)) fmtln("Found %d draft post(s).", len(imp.Posts)) // Create collections and their posts for _, coll := range imp.Collections { fmt.Printf("%s has %d post(s). ", coll.Alias, len(*coll.Posts)) if len(*coll.Posts) == 0 { fmt.Print("Skipping.\n") continue } fmt.Print("\n") if _, ok := userColls[coll.Alias]; ok { fmtln("Adding to your existing collection %s.", coll.Alias) } else { fmt.Printf("Creating collection %s...", coll.Alias) _, err = cl.CreateCollection(&writeas.CollectionParams{ Alias: coll.Alias, Title: coll.Title, Description: coll.Description, // TODO: //Stylesheet: coll.Stylesheet, //Public: coll.Public, }) if err != nil { // TODO: handle alias collisions // TODO: handle hitting collection allowance limit fmt.Fprintf(os.Stderr, "error: %v\n", err) continue } fmt.Print("OK\n") } // Create posts for _, p := range *coll.Posts { fmt.Printf("Creating post %s...", p.Slug) _, err = wfmigrate.CreatePost(cl, p, coll.Alias) if err != nil { fmt.Fprintf(os.Stderr, "error: %v\n", err) continue } fmt.Print("OK\n") } } // Create anonymous / draft posts for _, p := range imp.Posts { fmt.Printf("Creating draft post from %s...", p.ID) _, err = wfmigrate.CreatePost(cl, p, "") if err != nil { fmt.Fprintf(os.Stderr, "error: %v\n", err) continue } fmt.Print("OK\n") } } func fmtln(s string, v ...interface{}) { fmt.Printf(s+"\n", v...) } diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..5fb7eac --- /dev/null +++ b/go.mod @@ -0,0 +1,16 @@ +module github.com/writefreely/wf-migrate + +go 1.23.0 + +require ( + github.com/howeyc/gopass v0.0.0-20210920133722-c8aef6fb66ef + github.com/writeas/go-writeas/v2 v2.1.0 +) + +require ( + code.as/core/socks v1.0.0 // indirect + github.com/writeas/impart v1.1.1 // indirect + golang.org/x/crypto v0.28.0 // indirect + golang.org/x/sys v0.26.0 // indirect + golang.org/x/term v0.25.0 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..e684fe7 --- /dev/null +++ b/go.sum @@ -0,0 +1,15 @@ +code.as/core/socks v1.0.0 h1:SPQXNp4SbEwjOAP9VzUahLHak8SDqy5n+9cm9tpjZOs= +code.as/core/socks v1.0.0/go.mod h1:BAXBy5O9s2gmw6UxLqNJcVbWY7C/UPs+801CcSsfWOY= +github.com/howeyc/gopass v0.0.0-20210920133722-c8aef6fb66ef h1:A9HsByNhogrvm9cWb28sjiS3i7tcKCkflWFEkHfuAgM= +github.com/howeyc/gopass v0.0.0-20210920133722-c8aef6fb66ef/go.mod h1:lADxMC39cJJqL93Duh1xhAs4I2Zs8mKS89XWXFGp9cs= +github.com/writeas/go-writeas/v2 v2.1.0 h1:Wot4JX63ygKe/V30jwNYCBUgqjN4Tz0vrk9+Ujya1p4= +github.com/writeas/go-writeas/v2 v2.1.0/go.mod h1:9sjczQJKmru925fLzg0usrU1R1tE4vBmQtGnItUMR0M= +github.com/writeas/impart v1.1.0/go.mod h1:g0MpxdnTOHHrl+Ca/2oMXUHJ0PcRAEWtkCzYCJUXC9Y= +github.com/writeas/impart v1.1.1 h1:RyA9+CqbdbDuz53k+nXCWUY+NlEkdyw6+nWanxSBl5o= +github.com/writeas/impart v1.1.1/go.mod h1:g0MpxdnTOHHrl+Ca/2oMXUHJ0PcRAEWtkCzYCJUXC9Y= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= diff --git a/import.go b/import.go index eb7bc33..a9ef649 100644 --- a/import.go +++ b/import.go @@ -1,24 +1,24 @@ package wfmigrate -import "github.com/writeas/go-writeas" +import "github.com/writeas/go-writeas/v2" type Import struct { writeas.User Collections []writeas.Collection `json:"collections"` Posts []writeas.Post `json:"posts"` } // CreatePost publishes a post from the given writeas.Post. func CreatePost(cl *writeas.Client, p writeas.Post, collAlias string) (*writeas.Post, error) { return cl.CreatePost(&writeas.PostParams{ Slug: p.Slug, Title: p.Title, Content: p.Content, Font: p.Font, Language: p.Language, IsRTL: p.RTL, Created: &p.Created, Updated: &p.Updated, Collection: collAlias, }) }