diff --git a/.gitignore b/.gitignore index 1d24a02..fba1d76 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ *.exe *.png build/ +vendor/ diff --git a/README.md b/README.md index c701040..548ec76 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ Open up your command prompt: Reverse search a local file and open Google & TinEye results: ```batch -imgops "C:\my_file.jpg" google,tineye +imgops search "C:\my_file.jpg" -t google,tineye ``` ### Pass a URL @@ -31,5 +31,7 @@ imgops "C:\my_file.jpg" google,tineye Reverse search a URL and open Google results: ```batch -imgops "http://example.com/foobar.jpg" google +imgops search "http://example.com/foobar.jpg" -t google ``` + +Other available flags: `-s` (select a target from list) and `-r` (output search URL) diff --git a/glide.yaml b/glide.yaml new file mode 100644 index 0000000..86880e2 --- /dev/null +++ b/glide.yaml @@ -0,0 +1,11 @@ +package: . +import: +- package: github.com/PuerkitoBio/goquery +- package: github.com/parnurzeal/gorequest +- package: github.com/skratchdot/open-golang + subpackages: + - open +- package: github.com/tj/go-debug +- package: github.com/urfave/cli + version: v1.20.0 +- package: github.com/eiannone/keyboard diff --git a/main.go b/main.go index 22dab2c..747d732 100644 --- a/main.go +++ b/main.go @@ -4,64 +4,143 @@ import ( "fmt" "os" + "github.com/eiannone/keyboard" "github.com/skratchdot/open-golang/open" + "github.com/urfave/cli" ) import . "github.com/tj/go-debug" -var cmdAction string = "" var debug = Debug("imgops") -var QueryMap map[string]string = getIdMap() + +var authors = []cli.Author{ + { + Name: "Doğan Çelik", + Email: "dogancelik.com", + }, +} var Version string -func main() { - fmt.Printf("ImgOps %s by Doğan Çelik (dogancelik.com)\n", Version) +func cliSelect() string { + err := keyboard.Open() + if err != nil { + panic(err) + } + defer keyboard.Close() - cmdPath := "" - cmdAction = "" + fmt.Println(genSelectText()) + ret := "" - if len(os.Args) > 1 { - cmdPath = os.Args[1] - } else { - fmt.Println("No file or URL") - os.Exit(1) + for { + char, key, err := keyboard.GetKey() + if err != nil { + panic(err) + } else if key == keyboard.KeyEsc { + break + } + + m := getKeyToNameTargets(availableTargets) + target, mapOk := m[char] + if mapOk { + return target + } else if char == 'i' { + return defaultTarget + } } - if len(os.Args) > 2 { - cmdAction = os.Args[2] + return ret +} + +func cliSearch(c *cli.Context) error { + + if c.NArg() == 0 { + return cli.NewExitError("No file or URL is given", 1) } - debug("Path: %s", cmdPath) - debug("Action: %s", cmdAction) - debug("Queries: %v", QueryMap) + srcPath := c.Args().First() + targets := c.String("targets") + + debug("Path: %s", srcPath) + debug("Targets: %s", targets) var urls []string var errUpload error - if isUrl(cmdPath) == true { + + // Select flag + if c.Bool("select") { + targets = cliSelect() + if targets == "" { + return cli.NewExitError("Upload cancelled", 4) + } + } + + // Upload + if isUrl(srcPath) == true { debug("Start URL upload") - urls, errUpload = UploadURL(cmdPath, cmdAction) + urls, errUpload = UploadURL(srcPath, targets) } else { - - if _, err := os.Stat(cmdPath); os.IsNotExist(err) { - fmt.Println("File doesn't exist:", cmdPath) - os.Exit(2) + if _, err := os.Stat(srcPath); os.IsNotExist(err) { + return cli.NewExitError("File doesn't exist: "+srcPath, 2) } debug("Start file upload") - urls, errUpload = UploadFile(cmdPath, cmdAction) + urls, errUpload = UploadFile(srcPath, targets) } + // Upload result if errUpload != nil && len(urls) == 0 { - fmt.Println("Error during upload:", errUpload) - os.Exit(3) + return cli.NewExitError("Error during upload: "+errUpload.Error(), 3) } else { if errUpload != nil { - fmt.Printf("Warning wrong action '%s'; will open ImgOps instead\n", cmdAction) + fmt.Fprintf(os.Stderr, "Unknown targets '%s', will open default page instead", targets) } for _, url := range urls { - open.Start(url) + if c.Bool("return") { + fmt.Println(url) + } else { + open.Start(url) + } } } + return nil +} + +func cliMain(c *cli.Context) error { + cli.ShowAppHelp(c) + return nil +} + +func main() { + app := cli.NewApp() + app.Name = "ImgOps CLI" + app.Usage = "Reverse search images" + app.Version = Version + app.Authors = authors + app.Action = cliMain + app.Commands = []cli.Command{ + { + Name: "search", + Aliases: []string{"a"}, + Usage: "Search a file or a URL", + Action: cliSearch, + Flags: []cli.Flag{ + cli.StringFlag{ + Name: "targets, t", + Value: defaultTarget, + Usage: "Target website to search at (e.g. Google)", + }, + cli.BoolFlag{ + Name: "select, s", + Usage: "Show a list of targets to select from", + }, + cli.BoolFlag{ + Name: "return, r", + Usage: "Output the result URL", + }, + }, + }, + } + app.Run(os.Args) } diff --git a/targets.go b/targets.go new file mode 100644 index 0000000..e840b9e --- /dev/null +++ b/targets.go @@ -0,0 +1,70 @@ +package main + +type Target struct { + Name string + Key rune + Id string +} + +var availableTargets = []Target{ + { + Name: "google", + Key: 'g', + Id: "#t85", + }, + { + Name: "bing", + Key: 'b', + Id: "#t101", + }, + { + Name: "tineye", + Key: 't', + Id: "#t11", + }, + { + Name: "reddit", + Key: 'r', + Id: "#t97", + }, + { + Name: "yandex", + Key: 'y', + Id: "#t72", + }, + { + Name: "baidu", + Key: 'a', + Id: "#t74", + }, + { + Name: "so", + Key: 's', + Id: "#t109", + }, + { + Name: "sogou", + Key: 'u', + Id: "#t110", + }, +} + +func getKeyToNameTargets(targets []Target) map[rune]string { + m := make(map[rune]string) + + for _, target := range targets { + m[target.Key] = target.Name + } + + return m +} + +func getNameToIdTargets(targets []Target) map[string]string { + m := make(map[string]string) + + for _, target := range targets { + m[target.Name] = target.Id + } + + return m +} diff --git a/upload.go b/upload.go index 8033a36..42e0fcb 100644 --- a/upload.go +++ b/upload.go @@ -11,12 +11,13 @@ import ( const uploadUrl string = "https://imgops.com/upload/uploadPhoto-action.asp" const uploadSearch string = "userUploadTempCache" +const defaultTarget = "imgops" var defaultAction bool var finalUrl string func setDefaultAction(targetAction string) { - if targetAction != "" { + if targetAction != defaultTarget { defaultAction = false } else { defaultAction = true diff --git a/utils.go b/utils.go index 3aa2261..6b6ef69 100644 --- a/utils.go +++ b/utils.go @@ -12,19 +12,6 @@ func isUrl(targetPath string) bool { return strings.Contains(targetPath, "http:") || strings.Contains(targetPath, "https:") } -func getIdMap() map[string]string { - return map[string]string{ - "google": "#t85", - "bing": "#t101", - "tineye": "#t11", - "reddit": "#t97", - "yandex": "#t72", - "baidu": "#t74", - "so": "#t109", - "sogou": "#t110", - } -} - func findHref(document, targetStr, finalUrl string) ([]string, error) { doc, err := goquery.NewDocumentFromReader(strings.NewReader(document)) if err != nil { @@ -54,11 +41,12 @@ func findHref(document, targetStr, finalUrl string) ([]string, error) { // Returns queries of found targets func getQueryList(s string) []string { split := strings.Split(s, ",") + m := getNameToIdTargets(availableTargets) found := make([]string, 0, len(split)) for _, val := range split { key := strings.TrimSpace(val) - query, mapOk := QueryMap[key] + query, mapOk := m[key] if mapOk { debug("Query for '%s' is found: %s", key, query) found = append(found, query) @@ -67,3 +55,15 @@ func getQueryList(s string) []string { return found } + +// Create a nice select list + +func genSelectText() string { + text := "Select a target:\n\n" + text += " > [i]mgops\n" + for _, target := range availableTargets { + text += " > " + strings.Replace(target.Name, string(target.Key), "["+string(target.Key)+"]", 1) + "\n" + } + text += "\n(Press ESC to cancel)" + return text +}