diff --git a/cmd/mstdn/README.md b/cmd/mstdn/README.md index 6b2dd22..cc6f01c 100644 --- a/cmd/mstdn/README.md +++ b/cmd/mstdn/README.md @@ -28,6 +28,7 @@ COMMANDS: delete delete status init initialize profile mikami search mikami + xsearch cross search help, h Shows a list of commands or help for one command GLOBAL OPTIONS: diff --git a/cmd/mstdn/cmd_mikami.go b/cmd/mstdn/cmd_mikami.go index ec3449e..abbfc18 100644 --- a/cmd/mstdn/cmd_mikami.go +++ b/cmd/mstdn/cmd_mikami.go @@ -1,26 +1,9 @@ package main import ( - "fmt" - - "github.com/PuerkitoBio/goquery" "github.com/urfave/cli" ) func cmdMikami(c *cli.Context) error { - doc, err := goquery.NewDocument("http://mastodonsearch.jp/cross/?q=三上") - if err != nil { - return err - } - doc.Find(".post").Each(func(n int, elem *goquery.Selection) { - href, ok := elem.Find(".mst_content a").Attr("href") - if !ok { - return - } - text := elem.Find(".mst_content p").Text() - fmt.Println(href) - fmt.Println(text) - fmt.Println() - }) - return nil + return xSearch(c.App.Metadata["xsearch_url"].(string), "三上", c.App.Writer) } diff --git a/cmd/mstdn/cmd_mikami_test.go b/cmd/mstdn/cmd_mikami_test.go new file mode 100644 index 0000000..3fe9eae --- /dev/null +++ b/cmd/mstdn/cmd_mikami_test.go @@ -0,0 +1,41 @@ +package main + +import ( + "bytes" + "fmt" + "net/http" + "strings" + "testing" + + "github.com/urfave/cli" +) + +func TestCmdMikami(t *testing.T) { + ok := false + buf := bytes.NewBuffer(nil) + testWithServer( + func(w http.ResponseWriter, r *http.Request) { + if r.URL.Query().Get("q") == "三上" { + ok = true + fmt.Fprintln(w, `

三上

`) + } + }, + func(app *cli.App) { + app.Writer = buf + err := app.Run([]string{"mstdn", "mikami"}) + if err != nil { + t.Fatalf("should not be fail: %v", err) + } + }, + ) + if !ok { + t.Fatal("should be search Mikami") + } + result := buf.String() + if !strings.Contains(result, "http://example.com/@test/1") { + t.Fatalf("%q should be contained in output of search: %s", "http://example.com/@test/1", result) + } + if !strings.Contains(result, "三上") { + t.Fatalf("%q should be contained in output of search: %s", "三上", result) + } +} diff --git a/cmd/mstdn/cmd_test.go b/cmd/mstdn/cmd_test.go index 5bba072..14043c3 100644 --- a/cmd/mstdn/cmd_test.go +++ b/cmd/mstdn/cmd_test.go @@ -30,6 +30,7 @@ func testWithServer(h http.HandlerFunc, testFuncs ...func(*cli.App)) string { "config": &mastodon.Config{ Server: "https://example.com", }, + "xsearch_url": ts.URL, } for _, f := range testFuncs { diff --git a/cmd/mstdn/cmd_xsearch.go b/cmd/mstdn/cmd_xsearch.go index 1544d9f..2c7950b 100644 --- a/cmd/mstdn/cmd_xsearch.go +++ b/cmd/mstdn/cmd_xsearch.go @@ -2,6 +2,7 @@ package main import ( "fmt" + "io" "net/url" "github.com/PuerkitoBio/goquery" @@ -9,12 +10,16 @@ import ( ) func cmdXSearch(c *cli.Context) error { - u, err := url.Parse("http://mastodonsearch.jp/cross/") + return xSearch(c.App.Metadata["xsearch_url"].(string), c.Args().First(), c.App.Writer) +} + +func xSearch(xsearchRawurl, query string, w io.Writer) error { + u, err := url.Parse(xsearchRawurl) if err != nil { return err } params := url.Values{} - params.Set("q", c.Args().First()) + params.Set("q", query) u.RawQuery = params.Encode() doc, err := goquery.NewDocument(u.String()) if err != nil { @@ -26,9 +31,8 @@ func cmdXSearch(c *cli.Context) error { return } text := elem.Find(".mst_content p").Text() - fmt.Println(href) - fmt.Println(text) - fmt.Println() + fmt.Fprintf(w, "%s\n", href) + fmt.Fprintf(w, "%s\n\n", text) }) return nil } diff --git a/cmd/mstdn/cmd_xsearch_test.go b/cmd/mstdn/cmd_xsearch_test.go new file mode 100644 index 0000000..f3dc105 --- /dev/null +++ b/cmd/mstdn/cmd_xsearch_test.go @@ -0,0 +1,76 @@ +package main + +import ( + "bytes" + "fmt" + "net/http" + "net/http/httptest" + "strings" + "testing" + + "github.com/urfave/cli" +) + +func TestCmdXSearch(t *testing.T) { + testWithServer( + func(w http.ResponseWriter, r *http.Request) { + fmt.Fprintln(w, `

test status

`) + }, + func(app *cli.App) { + err := app.Run([]string{"mstdn", "xsearch", "test"}) + if err != nil { + t.Fatalf("should not be fail: %v", err) + } + }, + ) +} + +func TestXSearch(t *testing.T) { + canErr := true + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if canErr { + canErr = false + http.Error(w, http.StatusText(http.StatusInternalServerError), 9999) + return + } else if r.URL.Query().Get("q") == "empty" { + fmt.Fprintln(w, `

test status

`) + return + } + + fmt.Fprintln(w, `

test status

`) + })) + defer ts.Close() + + err := xSearch(":", "", nil) + if err == nil { + t.Fatalf("should be fail: %v", err) + } + + err = xSearch(ts.URL, "", nil) + if err == nil { + t.Fatalf("should be fail: %v", err) + } + + buf := bytes.NewBuffer(nil) + err = xSearch(ts.URL, "empty", buf) + if err != nil { + t.Fatalf("should not be fail: %v", err) + } + result := buf.String() + if result != "" { + t.Fatalf("the search result should be empty: %s", result) + } + + buf = bytes.NewBuffer(nil) + err = xSearch(ts.URL, "test", buf) + if err != nil { + t.Fatalf("should not be fail: %v", err) + } + result = buf.String() + if !strings.Contains(result, "http://example.com/@test/1") { + t.Fatalf("%q should be contained in output of search: %s", "http://example.com/@test/1", result) + } + if !strings.Contains(result, "test status") { + t.Fatalf("%q should be contained in output of search: %s", "test status", result) + } +} diff --git a/cmd/mstdn/main.go b/cmd/mstdn/main.go index a53c7f7..392f748 100644 --- a/cmd/mstdn/main.go +++ b/cmd/mstdn/main.go @@ -361,8 +361,9 @@ func run() int { client := mastodon.NewClient(config) app.Metadata = map[string]interface{}{ - "client": client, - "config": config, + "client": client, + "config": config, + "xsearch_url": "http://mastodonsearch.jp/cross/", } if config.AccessToken == "" { return authenticate(client, config, file)