main.go 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. package main
  2. import (
  3. "encoding/base64"
  4. "fmt"
  5. "log"
  6. "net"
  7. "os"
  8. "os/user"
  9. "path/filepath"
  10. "github.com/cryptix/go-muxrpc"
  11. "github.com/cryptix/go-muxrpc/codec"
  12. "github.com/cryptix/secretstream"
  13. "github.com/cryptix/secretstream/secrethandshake"
  14. "github.com/shurcooL/go-goon"
  15. "gopkg.in/errgo.v1"
  16. "gopkg.in/urfave/cli.v2"
  17. )
  18. var sbotAppKey []byte
  19. var defaultKeyFile string
  20. func init() {
  21. var err error
  22. sbotAppKey, err = base64.StdEncoding.DecodeString("1KHLiKZvAvjbY1ziZEHMXawbCEIM6qwjCDm3VYRan/s=")
  23. if err != nil {
  24. log.Fatal(err)
  25. }
  26. u, err := user.Current()
  27. if err != nil {
  28. log.Fatal(err)
  29. }
  30. defaultKeyFile = filepath.Join(u.HomeDir, ".ssb", "secret")
  31. }
  32. var Revision = "unset"
  33. func main() {
  34. var app cli.App
  35. app.Name = "ssb-pubit"
  36. app.Usage = "publishing data"
  37. cli.VersionPrinter = func(c *cli.Context) {
  38. // go install -ldflags="-X main.Revision=$(git rev-parse HEAD)"
  39. fmt.Printf("%s ( rev: %s )\n", c.App.Version, Revision)
  40. }
  41. app.Version = "alpha1"
  42. app.Flags = []cli.Flag{
  43. &cli.StringFlag{Name: "addr", Value: "localhost:8008", Usage: "tcp address of the sbot to connect to (or listen on)"},
  44. &cli.StringFlag{Name: "key,k", Value: defaultKeyFile},
  45. &cli.BoolFlag{Name: "verbose,vv", Usage: "print muxrpc packets"},
  46. }
  47. app.Before = initClient
  48. app.Commands = []*cli.Command{
  49. {
  50. Name: "meta",
  51. Action: metaCmd,
  52. Flags: []cli.Flag{},
  53. },
  54. {
  55. Name: "files",
  56. Action: filesCmd,
  57. Flags: []cli.Flag{
  58. &cli.StringFlag{Name: "root", Value: "", Usage: "the ID of the first message of the thread"},
  59. },
  60. },
  61. }
  62. if err := app.Run(os.Args); err != nil {
  63. log.Println("Error: ", err)
  64. }
  65. }
  66. var client *muxrpc.Client
  67. func initClient(ctx *cli.Context) error {
  68. log.SetOutput(os.Stderr)
  69. localKey, err := secrethandshake.LoadSSBKeyPair(ctx.String("key"))
  70. if err != nil {
  71. return err
  72. }
  73. var conn net.Conn
  74. c, err := secretstream.NewClient(*localKey, sbotAppKey)
  75. if err != nil {
  76. return err
  77. }
  78. d, err := c.NewDialer(localKey.Public)
  79. if err != nil {
  80. return err
  81. }
  82. conn, err = d("tcp", ctx.String("addr"))
  83. if err != nil {
  84. return err
  85. }
  86. if ctx.Bool("verbose") {
  87. client = muxrpc.NewClient(codec.Wrap(conn))
  88. } else {
  89. client = muxrpc.NewClient(conn)
  90. }
  91. return nil
  92. }
  93. func privatePublishCmd(ctx *cli.Context) error {
  94. content := map[string]interface{}{
  95. "text": ctx.String("text"),
  96. "type": ctx.String("type"),
  97. }
  98. if r := ctx.String("root"); r != "" {
  99. content["root"] = r
  100. if b := ctx.String("branch"); b != "" {
  101. content["branch"] = b
  102. } else {
  103. content["branch"] = r
  104. }
  105. }
  106. recps := ctx.StringSlice("recps")
  107. if len(recps) == 0 {
  108. return errgo.Newf("private.publish: 0 recps.. that would be quite the lonely message..")
  109. }
  110. arg := map[string]interface{}{
  111. "content": content,
  112. "rcps": recps,
  113. }
  114. var reply map[string]interface{}
  115. err := client.Call("private.publish", arg, &reply)
  116. if err != nil {
  117. return errgo.Notef(err, "publish call failed.")
  118. }
  119. log.Println("private published..!")
  120. goon.Dump(reply)
  121. return client.Close()
  122. }
  123. func privateUnboxCmd(ctx *cli.Context) error {
  124. id := ctx.Args().Get(0)
  125. if id == "" {
  126. return errgo.New("get: id can't be empty")
  127. }
  128. var getReply map[string]interface{}
  129. if err := client.Call("get", id, &getReply); err != nil {
  130. return errgo.Notef(err, "get call failed.")
  131. }
  132. log.Print("get:")
  133. goon.Dump(getReply)
  134. var reply map[string]interface{}
  135. if err := client.Call("private.unbox", getReply["content"], &reply); err != nil {
  136. return errgo.Notef(err, "get call failed.")
  137. }
  138. log.Print("unbox:")
  139. goon.Dump(reply)
  140. return client.Close()
  141. }
  142. func publishCmd(ctx *cli.Context) error {
  143. arg := map[string]interface{}{
  144. "text": ctx.String("text"),
  145. "type": ctx.String("type"),
  146. }
  147. if r := ctx.String("root"); r != "" {
  148. arg["root"] = r
  149. if b := ctx.String("branch"); b != "" {
  150. arg["branch"] = b
  151. } else {
  152. arg["branch"] = r
  153. }
  154. }
  155. var reply map[string]interface{}
  156. err := client.Call("publish", arg, &reply)
  157. if err != nil {
  158. return errgo.Notef(err, "publish call failed.")
  159. }
  160. log.Println("published..!")
  161. goon.Dump(reply)
  162. return client.Close()
  163. }
  164. func createHistoryStreamCmd(ctx *cli.Context) error {
  165. id := ctx.Args().Get(0)
  166. if id == "" {
  167. return errgo.New("createHist: id can't be empty")
  168. }
  169. arg := map[string]interface{}{
  170. "content": id,
  171. }
  172. reply := make([]map[string]interface{}, 0, 10)
  173. err := client.SyncSource("createHistoryStream", arg, &reply)
  174. if err != nil {
  175. return errgo.Notef(err, "createHistoryStream call failed.")
  176. }
  177. log.Println("got hist stream..!")
  178. goon.Dump(reply)
  179. return client.Close()
  180. }
  181. func createLogStream(ctx *cli.Context) error {
  182. reply := make([]map[string]interface{}, 0, 10)
  183. err := client.SyncSource("createLogStream", nil, &reply)
  184. if err != nil {
  185. return errgo.Notef(err, "createLogStream call failed.")
  186. }
  187. log.Println("got log stream..!")
  188. for _, p := range reply {
  189. goon.Dump(p)
  190. }
  191. return client.Close()
  192. }
  193. func callCmd(ctx *cli.Context) error {
  194. cmd := ctx.Args().Get(0)
  195. if cmd == "" {
  196. return errgo.New("call: cmd can't be empty")
  197. }
  198. arg := ctx.Args().Get(1)
  199. var reply interface{}
  200. if err := client.Call(cmd, arg, &reply); err != nil {
  201. return errgo.Notef(err, "%s: call failed.", cmd)
  202. }
  203. log.Print("call:")
  204. goon.Dump(reply)
  205. return client.Close()
  206. }