package main import ( "fmt" "log" "math/rand" "net/http" "net/url" "strconv" "strings" "time" "html/template" "github.com/PuerkitoBio/goquery" ) // Define a struct to represent search result type SearchResult struct { URL string Header string Description string } type LanguageOption struct { Code string Name string } var languageOptions = []LanguageOption{ {Code: "", Name: "Any Language"}, {Code: "lang_en", Name: "English"}, {Code: "lang_af", Name: "Afrikaans"}, {Code: "lang_ar", Name: "العربية (Arabic)"}, {Code: "lang_hy", Name: "Հայերեն (Armenian)"}, {Code: "lang_be", Name: "Беларуская (Belarusian)"}, {Code: "lang_bg", Name: "български (Bulgarian)"}, {Code: "lang_ca", Name: "Català (Catalan)"}, {Code: "lang_zh-CN", Name: "中文 (简体) (Chinese Simplified)"}, {Code: "lang_zh-TW", Name: "中文 (繁體) (Chinese Traditional)"}, {Code: "lang_hr", Name: "Hrvatski (Croatian)"}, {Code: "lang_cs", Name: "Čeština (Czech)"}, {Code: "lang_da", Name: "Dansk (Danish)"}, {Code: "lang_nl", Name: "Nederlands (Dutch)"}, {Code: "lang_eo", Name: "Esperanto"}, {Code: "lang_et", Name: "Eesti (Estonian)"}, {Code: "lang_tl", Name: "Filipino (Tagalog)"}, {Code: "lang_fi", Name: "Suomi (Finnish)"}, {Code: "lang_fr", Name: "Français (French)"}, {Code: "lang_de", Name: "Deutsch (German)"}, {Code: "lang_el", Name: "Ελληνικά (Greek)"}, {Code: "lang_iw", Name: "עברית (Hebrew)"}, {Code: "lang_hi", Name: "हिन्दी (Hindi)"}, {Code: "lang_hu", Name: "magyar (Hungarian)"}, {Code: "lang_is", Name: "íslenska (Icelandic)"}, {Code: "lang_id", Name: "Bahasa Indonesia (Indonesian)"}, {Code: "lang_it", Name: "italiano (Italian)"}, {Code: "lang_ja", Name: "日本語 (Japanese)"}, {Code: "lang_ko", Name: "한국어 (Korean)"}, {Code: "lang_lv", Name: "latviešu (Latvian)"}, {Code: "lang_lt", Name: "lietuvių (Lithuanian)"}, {Code: "lang_no", Name: "norsk (Norwegian)"}, {Code: "lang_fa", Name: "فارسی (Persian)"}, {Code: "lang_pl", Name: "polski (Polish)"}, {Code: "lang_pt", Name: "português (Portuguese)"}, {Code: "lang_ro", Name: "română (Romanian)"}, {Code: "lang_ru", Name: "русский (Russian)"}, {Code: "lang_sr", Name: "српски (Serbian)"}, {Code: "lang_sk", Name: "slovenčina (Slovak)"}, {Code: "lang_sl", Name: "slovenščina (Slovenian)"}, {Code: "lang_es", Name: "español (Spanish)"}, {Code: "lang_sw", Name: "Kiswahili (Swahili)"}, {Code: "lang_sv", Name: "svenska (Swedish)"}, {Code: "lang_th", Name: "ไทย (Thai)"}, {Code: "lang_tr", Name: "Türkçe (Turkish)"}, {Code: "lang_uk", Name: "українська (Ukrainian)"}, {Code: "lang_vi", Name: "Tiếng Việt (Vietnamese)"}, } var funcs = template.FuncMap{ "title": func(s string) string { return strings.Title(s) }, "url_for": func(filename string) string { return "/" + filename }, } var templates = template.Must(template.New("").Funcs(funcs).ParseFiles("templates/results.html")) func main() { // Serve static files from the 'static' directory http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("static")))) http.HandleFunc("/", handleSearch) http.HandleFunc("/search", handleSearch) fmt.Println("Server is listening on http://localhost:5000") log.Fatal(http.ListenAndServe(":5000", nil)) } func handleSearch(w http.ResponseWriter, r *http.Request) { var query, safe, lang string // Differentiate between GET and POST requests to correctly extract query, safe, and lang. if r.Method == "GET" { // Serve the search page if no query is provided for a GET request // Or extract the query parameters directly from the URL if present query = r.URL.Query().Get("q") if query == "" { http.ServeFile(w, r, "static/search.html") return } safe = r.URL.Query().Get("safe") lang = r.URL.Query().Get("lang") } else if r.Method == "POST" { // For a POST request, extract form values query = r.FormValue("q") safe = r.FormValue("safe") lang = r.FormValue("lang") } // Early return if query is empty if query == "" { http.ServeFile(w, r, "static/search.html") return } // Time start := time.Now() // Adjust the search URL based on safe search and language settings var safeParam string if safe == "active" { safeParam = "&safe=active" } else { safeParam = "&safe=off" } var langParam string if lang != "" { langParam = "&lr=" + lang } searchURL := "https://www.google.com/search?q=" + url.QueryEscape(query) + safeParam + langParam print(searchURL+"\n") req, err := http.NewRequest("GET", searchURL, nil) if err != nil { http.Error(w, "Failed to create request", http.StatusInternalServerError) return } // Random user agent userAgents := []string{ "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:107.0) Gecko/20100101 Firefox/107.0", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:106.0) Gecko/20100101 Firefox/106.0", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.1 Safari/605.1.15", } randIndex := rand.Intn(len(userAgents)) userAgent := userAgents[randIndex] req.Header.Set("User-Agent", userAgent) resp, err := http.DefaultClient.Do(req) if err != nil { http.Error(w, "Failed to fetch search results", http.StatusInternalServerError) return } defer resp.Body.Close() // Parse HTML doc, err := goquery.NewDocumentFromReader(resp.Body) if err != nil { http.Error(w, "Failed to parse HTML", http.StatusInternalServerError) return } // Retrieve links, headers, and descriptions var results []SearchResult doc.Find(".yuRUbf").Each(func(i int, s *goquery.Selection) { link := s.Find("a") href, _ := link.Attr("href") header := link.Find("h3").Text() header = strings.TrimSpace(strings.TrimSuffix(header, "›")) descSelection := doc.Find(".VwiC3b").Eq(i) description := "" if descSelection.Length() > 0 { description = descSelection.Text() } results = append(results, SearchResult{ URL: href, Header: header, Description: description, }) }) elapsed := time.Since(start) // Prepare data for rendering template data := struct { Results []SearchResult Query string Fetched string ElapsedTime string LanguageOptions []LanguageOption CurrentLang string }{ Results: results, Query: query, Fetched: fmt.Sprintf("Fetched the results in %.2f seconds", elapsed.Seconds()), ElapsedTime: strconv.FormatFloat(elapsed.Seconds(), 'f', 2, 64), LanguageOptions: languageOptions, CurrentLang: lang, } // Render template err = templates.ExecuteTemplate(w, "results.html", data) if err != nil { http.Error(w, "Failed to render template", http.StatusInternalServerError) return } }