Command line client for Write.as https://write.as/apps/cli
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.

149 lines
2.8 KiB

  1. package main
  2. import (
  3. "fmt"
  4. "github.com/writeas/writeas-cli/fileutils"
  5. "io/ioutil"
  6. "os"
  7. "path/filepath"
  8. "strings"
  9. )
  10. const (
  11. postsFile = "posts.psv"
  12. separator = `|`
  13. )
  14. // Post holds the basic authentication information for a Write.as post.
  15. type Post struct {
  16. ID string
  17. EditToken string
  18. }
  19. func userDataDir() string {
  20. return filepath.Join(parentDataDir(), dataDirName)
  21. }
  22. func dataDirExists() bool {
  23. return fileutils.Exists(userDataDir())
  24. }
  25. func createDataDir() {
  26. err := os.Mkdir(userDataDir(), 0700)
  27. if err != nil {
  28. if debug {
  29. panic(err)
  30. } else {
  31. Errorln("Error creating data directory: %s", err)
  32. return
  33. }
  34. }
  35. }
  36. func addPost(id, token string) error {
  37. f, err := os.OpenFile(filepath.Join(userDataDir(), postsFile), os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0600)
  38. if err != nil {
  39. return fmt.Errorf("Error creating local posts list: %s", err)
  40. }
  41. defer f.Close()
  42. l := fmt.Sprintf("%s%s%s\n", id, separator, token)
  43. if _, err = f.WriteString(l); err != nil {
  44. return fmt.Errorf("Error writing to local posts list: %s", err)
  45. }
  46. return nil
  47. }
  48. func tokenFromID(id string) string {
  49. post := fileutils.FindLine(filepath.Join(userDataDir(), postsFile), id)
  50. if post == "" {
  51. return ""
  52. }
  53. parts := strings.Split(post, separator)
  54. if len(parts) < 2 {
  55. return ""
  56. }
  57. return parts[1]
  58. }
  59. func removePost(id string) {
  60. fileutils.RemoveLine(filepath.Join(userDataDir(), postsFile), id)
  61. }
  62. func getPosts() *[]Post {
  63. lines := fileutils.ReadData(filepath.Join(userDataDir(), postsFile))
  64. posts := []Post{}
  65. if lines != nil && len(*lines) > 0 {
  66. parts := make([]string, 2)
  67. for _, l := range *lines {
  68. parts = strings.Split(l, separator)
  69. if len(parts) < 2 {
  70. continue
  71. }
  72. posts = append(posts, Post{ID: parts[0], EditToken: parts[1]})
  73. }
  74. }
  75. return &posts
  76. }
  77. func composeNewPost() (string, *[]byte) {
  78. f, err := fileutils.TempFile(os.TempDir(), "WApost", "txt")
  79. if err != nil {
  80. if debug {
  81. panic(err)
  82. } else {
  83. Errorln("Error creating temp file: %s", err)
  84. return "", nil
  85. }
  86. }
  87. f.Close()
  88. cmd := editPostCmd(f.Name())
  89. if cmd == nil {
  90. os.Remove(f.Name())
  91. fmt.Println(noEditorErr)
  92. return "", nil
  93. }
  94. cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr
  95. if err := cmd.Start(); err != nil {
  96. os.Remove(f.Name())
  97. if debug {
  98. panic(err)
  99. } else {
  100. Errorln("Error starting editor: %s", err)
  101. return "", nil
  102. }
  103. }
  104. // If something fails past this point, the temporary post file won't be
  105. // removed automatically. Calling function should handle this.
  106. if err := cmd.Wait(); err != nil {
  107. if debug {
  108. panic(err)
  109. } else {
  110. Errorln("Editor finished with error: %s", err)
  111. return "", nil
  112. }
  113. }
  114. post, err := ioutil.ReadFile(f.Name())
  115. if err != nil {
  116. if debug {
  117. panic(err)
  118. } else {
  119. Errorln("Error reading post: %s", err)
  120. return "", nil
  121. }
  122. }
  123. return f.Name(), &post
  124. }