From 9cd71ca9f84db907abd2a0583218602d2a06f974 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 27 Oct 2021 15:00:19 +0700 Subject: [PATCH] initialize and release 1.0.0 --- LICENSE | 21 +++++++++ README.md | 39 +++++++++++++++ go.mod | 3 ++ goduckgo.go | 133 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 196 insertions(+) create mode 100644 LICENSE create mode 100644 README.md create mode 100644 go.mod create mode 100644 goduckgo.go diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..3ec9a5b --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 Minoplhy + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..547b44d --- /dev/null +++ b/README.md @@ -0,0 +1,39 @@ +# DuckDuckGo-image-api + +This project is Go adaptation of Python3 forked [duckduckgo-image-api](https://github.com/joeyism/duckduckgo-images-api) . I made this modules because this module will be need in my future project . + +Contribution are always welcome + +# How to use + +Import + +# Example Use Cases + +#### Get Search Results +``` +func main() { + hunsen := goduckgo.Search(goduckgo.Query{Keyword: "duck"}) + fmt.Print(hunsen.Results) +} + +``` +#### Get Search Result Image +``` +func main() { + hunsen := goduckgo.Search(goduckgo.Query{Keyword: "duck"}) + for _, somtam := range hunsen.Results { + // This Can be use with all hunsen.Results(or anything.Results depending on your goduckgo.Search) + // e.g. Title or URL depending on what you want + fmt.Println(somtam.Image) + } +} +``` +#### Specific P and S +``` +func main() { + hunsen := goduckgo.Search(goduckgo.Query{Keyword: "duck", P: "1", S: "200"}) + fmt.Print(hunsen.Results) +} + +``` \ No newline at end of file diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..38e7e3b --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module test.re/goduckgo + +go 1.17 diff --git a/goduckgo.go b/goduckgo.go new file mode 100644 index 0000000..50b418b --- /dev/null +++ b/goduckgo.go @@ -0,0 +1,133 @@ +package goduckgo + +import ( + "encoding/json" + "io/ioutil" + "log" + "net/http" + "os" + "regexp" + "time" +) + +type Gogo struct { + Ads interface{} `json:"ads"` + Next string `json:"next"` + Query string `json:"query"` + QueryEncoded string `json:"queryEncoded"` + ResponseType string `json:"response_type"` + Results []struct { + Height int `json:"height"` + Image string `json:"image"` + Source string `json:"source"` + Thumbnail string `json:"thumbnail"` + Title string `json:"title"` + URL string `json:"url"` + Width int `json:"width"` + } `json:"results"` +} + +type Query struct { + Keyword, P, S string +} + +type regex_r struct { + Regex, Body string +} + +// Hit duckduckgo for results +// NOTE: this module for now can only get p=1 s=0 results +func Search(keyword Query) Gogo { + + if keyword.Keyword == "" { + log.Fatal("No Query!") + os.Exit(3) + } + if keyword.P == "" { + keyword.P = "1" + } + + if keyword.S == "" { + keyword.S = "0" + } + + url := "https://duckduckgo.com/" + + log.Print("Hitting DuckDuckGo for Token") + + // First make a request to above URL, and parse out the 'vqd' + // This is a special token, which should be used in the subsequent request + + netreq := http.Client{ + Timeout: time.Second * 20, // Timeout is 20 Seconds + } + + requrl := url + "?q=" + keyword.Keyword + req, err := http.NewRequest(http.MethodGet, requrl, nil) + if err != nil { + log.Fatal(err) + } + req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:93.0) Gecko/20100101 Firefox/93.0") + + res, err := netreq.Do(req) + if err != nil { + log.Fatal(err) + } + + if res.Body != nil { + defer res.Body.Close() + } + + body, readErr := ioutil.ReadAll(res.Body) + if readErr != nil { + log.Fatal(readErr) + } + + hunsen := regexfind(regex_r{Regex: `vqd=([\d-]+)\&`, Body: string(body)}) + + if hunsen == "" { + log.Fatal("Token Parsing Failed !") + os.Exit(3) + } else { + log.Println("Obtained Token") + } + + requrl = url + "i.js" + "?l=us-en&o=json&q=" + keyword.Keyword + "&" + hunsen + "f=,,,&v7exp=a&p=" + keyword.P + "&s=" + keyword.S + log.Print("Hitting Url : " + requrl) + + resq, err := http.NewRequest(http.MethodGet, requrl, nil) + resq.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:93.0) Gecko/20100101 Firefox/93.0") + resq.Header.Add("accept", "application/json, text/javascript, */* q=0.01") + resq.Header.Add("authority", "duckduckgo.com") + resq.Header.Add("sec-fetch-dest", "Empty") + resq.Header.Add("x-requested-with", "XMLHttpRequest") + resq.Header.Add("sec-fetch-site", "same-origin") + resq.Header.Add("sec-fetch-mode", "cors") + resq.Header.Add("referer", "https://duckduckgo.com/") + resq.Header.Add("accept-language", "en-US,enq=0.9") + if err != nil { + log.Fatal(err) + } + resqs, getErr := netreq.Do(resq) + if getErr != nil { + log.Fatal(getErr) + } + + brudy, readErr := ioutil.ReadAll(resqs.Body) + if readErr != nil { + log.Fatal(readErr) + } + duckduck := Gogo{} + jsonErr := json.Unmarshal(brudy, &duckduck) + if jsonErr != nil { + log.Fatal(jsonErr) + } + log.Println("\nHitting Url Success : " + requrl) + return duckduck +} + +func regexfind(hitin regex_r) string { + gexgex := regexp.MustCompile(hitin.Regex) + hunsen := gexgex.FindString(string(hitin.Body)) + return hunsen +}