From a3cc5fd9e6655b48a473b6df5e4720ca943de657 Mon Sep 17 00:00:00 2001 From: Yasuhiro Matsumoto Date: Fri, 14 Apr 2017 01:00:02 +0900 Subject: [PATCH] add cmd/mstdn --- cmd/mstdn/main.go | 143 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 143 insertions(+) create mode 100644 cmd/mstdn/main.go diff --git a/cmd/mstdn/main.go b/cmd/mstdn/main.go new file mode 100644 index 0000000..de864a0 --- /dev/null +++ b/cmd/mstdn/main.go @@ -0,0 +1,143 @@ +package main + +import ( + "bufio" + "bytes" + "encoding/json" + "fmt" + "io/ioutil" + "log" + "os" + "path/filepath" + "runtime" + "strings" + + "github.com/mattn/go-mastodon" + "github.com/mattn/go-tty" + "golang.org/x/net/html" +) + +var blockTags = []string{"div", "br", "p", "blockquote", "pre", "h1", "h2", "h3", "h4", "h5", "h6"} + +func extractText(node *html.Node, w *bytes.Buffer) { + if node.Type == html.TextNode { + data := strings.Trim(node.Data, "\r\n") + if data != "" { + w.WriteString(data) + } + } else if node.Type == html.ElementNode { + if node.Data == "li" { + w.WriteString("\n* ") + } + } + for c := node.FirstChild; c != nil; c = c.NextSibling { + extractText(c, w) + } + if node.Type == html.ElementNode { + for _, bt := range blockTags { + if strings.ToLower(node.Data) == bt { + w.WriteString("\n") + break + } + } + } +} + +func prompt() (string, string, error) { + t, err := tty.Open() + if err != nil { + return "", "", err + } + defer t.Close() + + fmt.Print("E-Mail: ") + b, _, err := bufio.NewReader(os.Stdin).ReadLine() + if err != nil { + return "", "", err + } + email := string(b) + + fmt.Print("Password: ") + password, err := t.ReadPassword() + if err != nil { + return "", "", err + } + return email, password, nil +} + +func getConfig() (string, *mastodon.Config, error) { + dir := os.Getenv("HOME") + if dir == "" && runtime.GOOS == "windows" { + dir = os.Getenv("APPDATA") + if dir == "" { + dir = filepath.Join(os.Getenv("USERPROFILE"), "Application Data", "mstdn") + } + dir = filepath.Join(dir, "mstdn") + } else { + dir = filepath.Join(dir, ".config", "mstdn") + } + if err := os.MkdirAll(dir, 0700); err != nil { + return "", nil, err + } + file := filepath.Join(dir, "settings.json") + b, err := ioutil.ReadFile(file) + if err != nil && !os.IsNotExist(err) { + return "", nil, err + } + config := &mastodon.Config{ + Server: "https://mstdn.jp", + ClientID: "654a15390204e70d74f8d9264526e017e26d323e20e3f983409c157115009862", + ClientSecret: "17274242a0846ebadcdda77727666c9d475f1989b56ad9bd959021f62f92a84c", + } + if err == nil { + err = json.Unmarshal(b, &config) + if err != nil { + return "", nil, fmt.Errorf("could not unmarshal %v: %v", file, err) + } + } + return file, config, nil +} + +func main() { + file, config, err := getConfig() + if err != nil { + log.Fatal(err) + } + + c := mastodon.NewClient(config) + + if config.AccessToken == "" { + email, password, err := prompt() + if err != nil { + log.Fatal(err) + } + err = c.Authenticate(email, password) + if err != nil { + log.Fatal(err) + } + b, err := json.MarshalIndent(config, "", " ") + if err != nil { + log.Fatal("failed to store file:", err) + } + err = ioutil.WriteFile(file, b, 0700) + if err != nil { + log.Fatal("failed to store file:", err) + } + return + } + + timeline, err := c.GetTimeline("/api/v1/timelines/home") + if err != nil { + log.Fatal(err) + } + for _, t := range timeline { + doc, err := html.Parse(strings.NewReader(t.Content)) + if err != nil { + log.Fatal(err) + } + var buf bytes.Buffer + extractText(doc, &buf) + fmt.Println(t.Account.Username) + fmt.Println(buf.String()) + } +}