typo fix lol
This commit is contained in:
parent
84a88d6fe6
commit
96dae70aa9
4 changed files with 132 additions and 70 deletions
2
go.mod
2
go.mod
|
@ -1,6 +1,6 @@
|
||||||
module searchengine
|
module searchengine
|
||||||
|
|
||||||
go 1.18
|
go 1.21.6
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/PuerkitoBio/goquery v1.9.1 // indirect
|
github.com/PuerkitoBio/goquery v1.9.1 // indirect
|
||||||
|
|
71
imageresults.go
Normal file
71
imageresults.go
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"math/rand"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
var 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",
|
||||||
|
}
|
||||||
|
|
||||||
|
type ImageResult struct {
|
||||||
|
ThumbnailURL string `json:"thumb_proxy"`
|
||||||
|
Source string `json:"source"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func FetchImageResults(query string) ([]ImageResult, error) {
|
||||||
|
var results []ImageResult
|
||||||
|
|
||||||
|
// Random user agent
|
||||||
|
randIndex := rand.Intn(len(userAgents))
|
||||||
|
userAgent := userAgents[randIndex]
|
||||||
|
|
||||||
|
client := &http.Client{}
|
||||||
|
reqURL := fmt.Sprintf("https://api.qwant.com/v3/search/images?t=images&q=%s&count=50&locale=en_CA&offset=1&device=desktop&tgp=2&safesearch=1", url.QueryEscape(query))
|
||||||
|
req, err := http.NewRequest("GET", reqURL, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
req.Header.Set("User-Agent", userAgent)
|
||||||
|
|
||||||
|
resp, err := client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
var respData struct {
|
||||||
|
Data struct {
|
||||||
|
Result struct {
|
||||||
|
Items []struct {
|
||||||
|
Thumbnail string `json:"thumbnail"`
|
||||||
|
URL string `json:"url"`
|
||||||
|
} `json:"items"`
|
||||||
|
} `json:"result"`
|
||||||
|
} `json:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := json.NewDecoder(resp.Body).Decode(&respData); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, item := range respData.Data.Result.Items {
|
||||||
|
// Process each image result here
|
||||||
|
results = append(results, ImageResult{
|
||||||
|
ThumbnailURL: "/img_proxy?url=" + url.QueryEscape(item.Thumbnail),
|
||||||
|
Source: url.QueryEscape(urlparse(item.URL).Host), // Ensure you have a urlparse equivalent in Go or process URL differently
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return results, nil
|
||||||
|
}
|
42
main.go
42
main.go
|
@ -10,10 +10,16 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
"html/template"
|
"html/template"
|
||||||
|
|
||||||
"github.com/PuerkitoBio/goquery"
|
"github.com/PuerkitoBio/goquery"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Define a struct to represent search result
|
||||||
|
type SearchResult struct {
|
||||||
|
URL string
|
||||||
|
Header string
|
||||||
|
Description string
|
||||||
|
}
|
||||||
|
|
||||||
var funcs = template.FuncMap{
|
var funcs = template.FuncMap{
|
||||||
"title": func(s string) string {
|
"title": func(s string) string {
|
||||||
return strings.Title(s)
|
return strings.Title(s)
|
||||||
|
@ -81,20 +87,28 @@ func handleSearch(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Retrieve links
|
// Retrieve links, headers, and descriptions
|
||||||
var results [][]string
|
var results []SearchResult
|
||||||
doc.Find(".yuRUbf").Each(func(i int, s *goquery.Selection) {
|
doc.Find(".yuRUbf").Each(func(i int, s *goquery.Selection) {
|
||||||
link := s.Find("a")
|
link := s.Find("a")
|
||||||
href, _ := link.Attr("href")
|
href, _ := link.Attr("href")
|
||||||
title := link.Text()
|
// Extract header/title
|
||||||
results = append(results, []string{href, title})
|
header := link.Find("h3").Text()
|
||||||
})
|
// Remove the unwanted text from the header/title
|
||||||
|
header = strings.TrimSpace(strings.TrimSuffix(header, "›"))
|
||||||
|
|
||||||
// Retrieve description
|
// Retrieve corresponding description
|
||||||
var descriptions []string
|
descSelection := doc.Find(".VwiC3b").Eq(i)
|
||||||
doc.Find(".VwiC3b").Each(func(i int, s *goquery.Selection) {
|
description := ""
|
||||||
desc := s.Text()
|
if descSelection.Length() > 0 {
|
||||||
descriptions = append(descriptions, desc)
|
description = descSelection.Text()
|
||||||
|
}
|
||||||
|
|
||||||
|
results = append(results, SearchResult{
|
||||||
|
URL: href,
|
||||||
|
Header: header,
|
||||||
|
Description: description,
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
// Retrieve kno-rdesc
|
// Retrieve kno-rdesc
|
||||||
|
@ -117,9 +131,9 @@ func handleSearch(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
elapsed := time.Since(start)
|
elapsed := time.Since(start)
|
||||||
|
|
||||||
// Render template
|
// Prepare data for rendering template
|
||||||
data := struct {
|
data := struct {
|
||||||
Results [][]string
|
Results []SearchResult
|
||||||
Title string
|
Title string
|
||||||
Query string
|
Query string
|
||||||
Fetched string
|
Fetched string
|
||||||
|
@ -137,6 +151,8 @@ func handleSearch(w http.ResponseWriter, r *http.Request) {
|
||||||
RdescLink: knoLink,
|
RdescLink: knoLink,
|
||||||
ElapsedTime: strconv.FormatFloat(elapsed.Seconds(), 'f', 2, 64),
|
ElapsedTime: strconv.FormatFloat(elapsed.Seconds(), 'f', 2, 64),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Render template
|
||||||
err = templates.ExecuteTemplate(w, "results.html", data)
|
err = templates.ExecuteTemplate(w, "results.html", data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, "Failed to render template", http.StatusInternalServerError)
|
http.Error(w, "Failed to render template", http.StatusInternalServerError)
|
||||||
|
|
|
@ -1,12 +1,10 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>{{ .Title }}</title>
|
<title>{{.Query}} - Search Results</title>
|
||||||
<link rel="stylesheet" type="text/css" href="/static/style.css">
|
|
||||||
<style>
|
<style>
|
||||||
body {
|
body {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
@ -57,35 +55,15 @@
|
||||||
transition: background-color 0.3s ease;
|
transition: background-color 0.3s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.results-search-container .sub-search-button-wrapper button img {
|
|
||||||
vertical-align: middle;
|
|
||||||
margin-right: 5px; /* Adjust the margin between the icon and text */
|
|
||||||
}
|
|
||||||
|
|
||||||
.results-search-container .sub-search-button-wrapper button:hover {
|
.results-search-container .sub-search-button-wrapper button:hover {
|
||||||
background-color: #0056b3; /* Change the button hover background color to your preference */
|
background-color: #0056b3; /* Change the button hover background color to your preference */
|
||||||
}
|
}
|
||||||
|
|
||||||
.fetched {
|
.fetched, .snip, .snipp, .results {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
margin-top: 20px;
|
margin-top: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.snip,
|
|
||||||
.snipp {
|
|
||||||
text-align: center;
|
|
||||||
margin-top: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.results {
|
|
||||||
background-color: #fff; /* Change the background color to your preference */
|
|
||||||
padding: 20px;
|
|
||||||
margin: 20px auto;
|
|
||||||
border-radius: 8px;
|
|
||||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); /* Add a subtle shadow effect */
|
|
||||||
max-width: 600px; /* Adjust the max-width to your preference */
|
|
||||||
}
|
|
||||||
|
|
||||||
.results a {
|
.results a {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
color: #007bff; /* Change the link color to your preference */
|
color: #007bff; /* Change the link color to your preference */
|
||||||
|
@ -104,7 +82,6 @@
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<form action="/search" class="results-search-container" method="post" autocomplete="off">
|
<form action="/search" class="results-search-container" method="post" autocomplete="off">
|
||||||
<h1 class="logomobile"><a class="no-decoration" href="./">Tails<span class="X">Go</span></a></h1>
|
<h1 class="logomobile"><a class="no-decoration" href="./">Tails<span class="X">Go</span></a></h1>
|
||||||
|
@ -113,21 +90,19 @@
|
||||||
<button name="t"><img src="/static/searchicon.png" alt="text result" />General</button>
|
<button name="t"><img src="/static/searchicon.png" alt="text result" />General</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
<p class="fetched">{{ .Fetched }}</p>
|
<!-- <h1>Search Results for "{{.Query}}"</h1> -->
|
||||||
{{ if ne .KnoRdesc "" }}
|
|
||||||
<p class="snip">{{ .KnoRdesc }} <a target="_blank" href="{{ .RdescLink }}">{{ .RdescLink }}</a></p>
|
|
||||||
{{ end }}
|
|
||||||
{{ if ne .Snippet "" }}
|
|
||||||
<p class="snipp">{{ .Snippet }} <a target="_blank" href="{{ index .Results 0 0 }}">{{ index .Results 0 0 }}</a></p>
|
|
||||||
{{ end }}
|
|
||||||
{{ if .Results }}
|
|
||||||
{{ range .Results }}
|
|
||||||
<div class="results">
|
|
||||||
<a href="{{ . }}">{{ . }}<h3>{{ . }}</h3></a>
|
|
||||||
<p>{{ . }}</p>
|
|
||||||
</div>
|
|
||||||
{{ end }}
|
|
||||||
{{ end }}
|
|
||||||
</body>
|
|
||||||
|
|
||||||
|
{{range .Results}}
|
||||||
|
<div>
|
||||||
|
<a href="{{.URL}}">{{.Header}}</a><br>
|
||||||
|
<span>{{.Description}}</span>
|
||||||
|
</div>
|
||||||
|
<br>
|
||||||
|
{{end}}
|
||||||
|
<!-- <p>{{.Fetched}}</p>
|
||||||
|
<p>{{.Snippet}}</p>
|
||||||
|
<p>{{.KnoRdesc}}</p>
|
||||||
|
<p>{{.ElapsedTime}}</p>
|
||||||
|
<p>{{.RdescLink}}</p> -->
|
||||||
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
Loading…
Add table
Reference in a new issue