diff --git a/api/api.go b/api/api.go index 032d69f..f6cd7c2 100644 --- a/api/api.go +++ b/api/api.go @@ -1,267 +1,260 @@ package api import ( "fmt" - "path/filepath" "github.com/atotto/clipboard" writeas "github.com/writeas/go-writeas/v2" "github.com/writeas/web-core/posts" "github.com/writeas/writeas-cli/config" - "github.com/writeas/writeas-cli/fileutils" "github.com/writeas/writeas-cli/log" cli "gopkg.in/urfave/cli.v1" ) func client(userAgent string, tor bool) *writeas.Client { var client *writeas.Client if tor { client = writeas.NewTorClient(TorPort) } else { if config.IsDev() { client = writeas.NewDevClient() } else { client = writeas.NewClient() } } client.UserAgent = userAgent return client } func NewClient(c *cli.Context, authRequired bool) (*writeas.Client, error) { var client *writeas.Client if config.IsTor(c) { client = writeas.NewTorClient(TorPort) } else { if config.IsDev() { client = writeas.NewDevClient() } else { client = writeas.NewClient() } } client.UserAgent = config.UserAgent(c) // TODO: load user into var shared across the app u, _ := config.LoadUser(c) if u != nil { client.SetToken(u.AccessToken) } else if authRequired { return nil, fmt.Errorf("Not currently logged in. Authenticate with: writeas auth ") } return client, nil } // DoFetch retrieves the Write.as post with the given friendlyID, // optionally via the Tor hidden service. func DoFetch(friendlyID, ua string, tor bool) error { cl := client(ua, tor) p, err := cl.GetPost(friendlyID) if err != nil { return err } if p.Title != "" { fmt.Printf("# %s\n\n", string(p.Title)) } fmt.Printf("%s\n", string(p.Content)) return nil } // DoFetchPosts retrieves all remote posts for the // authenticated user func DoFetchPosts(c *cli.Context) ([]writeas.Post, error) { cl, err := NewClient(c, true) if err != nil { return nil, err } posts, err := cl.GetUserPosts() if err != nil { return nil, err } return *posts, nil } // DoPost creates a Write.as post, returning an error if it was // unsuccessful. func DoPost(c *cli.Context, post []byte, font string, encrypt, tor, code bool) (*writeas.Post, error) { cl, _ := NewClient(c, false) pp := &writeas.PostParams{ Font: config.GetFont(code, font), Collection: config.Collection(c), } pp.Title, pp.Content = posts.ExtractTitle(string(post)) if lang := config.Language(c, true); lang != "" { pp.Language = &lang } p, err := cl.CreatePost(pp) if err != nil { return nil, fmt.Errorf("Unable to post: %v", err) } var url string if p.Collection != nil { url = p.Collection.URL + p.Slug } else { if tor { url = config.TorBaseURL } else if config.IsDev() { url = config.DevBaseURL } else { url = config.WriteasBaseURL } url += "/" + p.ID // Output URL in requested format if c.Bool("md") { url += ".md" } } if cl.Token() == "" { // Store post locally, since we're not authenticated AddPost(c, p.ID, p.Token) } // Copy URL to clipboard err = clipboard.WriteAll(string(url)) if err != nil { log.Errorln("writeas: Didn't copy to clipboard: %s", err) } else { log.Info(c, "Copied to clipboard.") } // Output URL fmt.Printf("%s\n", url) return p, nil } // DoFetchCollections retrieves a list of the currently logged in users // collections. func DoFetchCollections(c *cli.Context) ([]RemoteColl, error) { cl, err := NewClient(c, true) if err != nil { if config.Debug() { log.ErrorlnQuit("could not create new client: %v", err) } return nil, fmt.Errorf("Couldn't create new client") } colls, err := cl.GetUserCollections() if err != nil { if config.Debug() { log.ErrorlnQuit("failed fetching user collections: %v", err) } return nil, fmt.Errorf("Couldn't get user collections") } out := make([]RemoteColl, len(*colls)) for i, c := range *colls { coll := RemoteColl{ Alias: c.Alias, Title: c.Title, URL: c.URL, } out[i] = coll } return out, nil } // DoUpdate updates the given post on Write.as. func DoUpdate(c *cli.Context, post []byte, friendlyID, token, font string, tor, code bool) error { cl, _ := NewClient(c, false) params := writeas.PostParams{} params.Title, params.Content = posts.ExtractTitle(string(post)) if lang := config.Language(c, false); lang != "" { params.Language = &lang } if code || font != "" { params.Font = config.GetFont(code, font) } _, err := cl.UpdatePost(friendlyID, token, ¶ms) if err != nil { if config.Debug() { log.ErrorlnQuit("Problem updating: %v", err) } return fmt.Errorf("Post doesn't exist, or bad edit token given.") } if tor { log.Info(c, "Post updated via hidden service.") } else { log.Info(c, "Post updated.") } return nil } // DoDelete deletes the given post on Write.as, and removes any local references func DoDelete(c *cli.Context, friendlyID, token string, tor bool) error { cl, _ := NewClient(c, false) err := cl.DeletePost(friendlyID, token) if err != nil { if config.Debug() { log.ErrorlnQuit("Problem deleting: %v", err) } return fmt.Errorf("Post doesn't exist, or bad edit token given.") } if tor { log.Info(c, "Post deleted from hidden service.") } else { log.Info(c, "Post deleted.") } RemovePost(c.App.ExtraInfo()["configDir"], friendlyID) return nil } func DoLogIn(c *cli.Context, username, password string) error { cl := client(config.UserAgent(c), config.IsTor(c)) u, err := cl.LogIn(username, password) if err != nil { if config.Debug() { log.ErrorlnQuit("Problem logging in: %v", err) } return err } err = config.SaveUser(c, u) if err != nil { return err } log.Info(c, "Logged in as %s.\n", u.User.Username) return nil } func DoLogOut(c *cli.Context) error { cl, err := NewClient(c, true) if err != nil { return err } err = cl.LogOut() if err != nil { if config.Debug() { log.ErrorlnQuit("Problem logging out: %v", err) } return err } - // Delete local user data - err = fileutils.DeleteFile(filepath.Join(config.UserDataDir(c.App.ExtraInfo()["configDir"]), config.UserFile)) - if err != nil { - return err - } - - return nil + // delete local user file + return config.DeleteUser(c) } diff --git a/config/directories.go b/config/directories.go index a24cc31..e2a68f3 100644 --- a/config/directories.go +++ b/config/directories.go @@ -1,38 +1,40 @@ package config import ( "os" "path/filepath" "github.com/writeas/writeas-cli/fileutils" "github.com/writeas/writeas-cli/log" ) +// UserDataDir returns a platform specific directory under the user's home +// directory func UserDataDir(dataDirName string) string { return filepath.Join(parentDataDir(), dataDirName) } func dataDirExists(dataDirName string) bool { return fileutils.Exists(dataDirName) } func createDataDir(dataDirName string) error { return os.Mkdir(dataDirName, 0700) } // DirMustExist checks for a directory, creates it if not found and either // panics or logs and error depending on the status of Debug func DirMustExist(dataDirName string) { // Ensure we have a data directory to use if !dataDirExists(dataDirName) { err := createDataDir(dataDirName) if err != nil { if Debug() { panic(err) } else { log.Errorln("Error creating data directory: %s", err) return } } } } diff --git a/config/user.go b/config/user.go index 6722452..52dd972 100644 --- a/config/user.go +++ b/config/user.go @@ -1,66 +1,77 @@ package config import ( "encoding/json" "io/ioutil" "path/filepath" writeas "github.com/writeas/go-writeas/v2" "github.com/writeas/writeas-cli/fileutils" "gopkg.in/urfave/cli.v1" ) const UserFile = "user.json" func LoadUser(c *cli.Context) (*writeas.AuthUser, error) { dir, err := userHostDir(c) if err != nil { return nil, err } fname := filepath.Join(dir, UserFile) userJSON, err := ioutil.ReadFile(fname) if err != nil { if !fileutils.Exists(fname) { // Don't return a file-not-found error return nil, nil } return nil, err } // Parse JSON file u := &writeas.AuthUser{} err = json.Unmarshal(userJSON, u) if err != nil { return nil, err } return u, nil } +func DeleteUser(c *cli.Context) error { + dir, err := userHostDir(c) + if err != nil { + return err + } + + return fileutils.DeleteFile(filepath.Join(dir, UserFile)) +} + func SaveUser(c *cli.Context, u *writeas.AuthUser) error { // Marshal struct into pretty-printed JSON userJSON, err := json.MarshalIndent(u, "", " ") if err != nil { return err } dir, err := userHostDir(c) if err != nil { return err } DirMustExist(dir) // Save file err = ioutil.WriteFile(filepath.Join(dir, UserFile), userJSON, 0600) if err != nil { return err } return nil } +// userHostDir returns the path to the user data directory with the host based +// subpath if the host flag is set func userHostDir(c *cli.Context) (string, error) { dataDir := UserDataDir(c.App.ExtraInfo()["configDir"]) hostDir, err := HostDirectory(c) if err != nil { return "", err } return filepath.Join(dataDir, hostDir), nil }