rkihacker commited on
Commit
075f035
·
verified ·
1 Parent(s): 80840b8

Update main.py

Browse files
Files changed (1) hide show
  1. main.py +57 -70
main.py CHANGED
@@ -1,74 +1,61 @@
1
  import httpx
2
- from bs4 import BeautifulSoup
3
- from fastapi import FastAPI, HTTPException
4
- from pydantic import BaseModel
5
- import uvicorn
6
-
7
- app = FastAPI()
8
-
9
- class SearchQuery(BaseModel):
10
- query: str
11
-
12
- class BraveSearch:
13
- def __init__(self, query):
14
- self.query = query
15
- self.url = f"https://search.brave.com/search?q={query.replace(' ', '+')}&source=web"
16
-
17
- async def fetch_results(self):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
  try:
19
- async with httpx.AsyncClient() as client:
20
- response = await client.get(self.url)
21
- response.raise_for_status()
22
-
23
- soup = BeautifulSoup(response.text, "html.parser")
24
- results = {
25
- "searchResults": [],
26
- "additionalData": [],
27
- "faq": []
28
- }
29
-
30
- for el in soup.select(".snippet"):
31
- title = el.select_one(".title")
32
- description = el.select_one(".snippet-description")
33
- link = el.select_one("a")
34
- results["searchResults"].append({
35
- "title": title.text.strip() if title else "No Title",
36
- "description": description.text.strip() if description else "No Description",
37
- "link": link["href"] if link else "#"
38
- })
39
 
40
- for el in soup.select(".t-tertiary.svelte-1yt5tdo"):
41
- attribution = el.select_one(".attribution")
42
- citation_link = el.select_one("cite a")
43
- results["additionalData"].append({
44
- "attribution": attribution.text.strip() if attribution else "No Attribution",
45
- "citationLink": citation_link["href"] if citation_link else "#"
46
- })
47
-
48
- for el in soup.select(".fq-item"):
49
- question = el.select_one(".faq-q")
50
- answer = el.select_one(".faq-a")
51
- faq_link = el.select_one("a")
52
- results["faq"].append({
53
- "question": question.text.strip() if question else "No Question",
54
- "answer": answer.text.strip() if answer else "No Answer",
55
- "faqLink": faq_link["href"] if faq_link else "#"
56
- })
57
-
58
- return results
59
  except httpx.HTTPStatusError as e:
60
- raise HTTPException(status_code=e.response.status_code, detail=f"HTTP error occurred: {e}")
61
- except Exception as e:
62
- raise HTTPException(status_code=500, detail=f"An error occurred: {e}")
63
-
64
- @app.post("/search")
65
- async def search(search_query: SearchQuery):
66
- if not search_query.query:
67
- raise HTTPException(status_code=400, detail="Query is required")
68
-
69
- search = BraveSearch(search_query.query)
70
- data = await search.fetch_results()
71
- return data
72
-
73
- if __name__ == "__main__":
74
- uvicorn.run(app, host="0.0.0.0", port=8000)
 
1
  import httpx
2
+ from fastapi import FastAPI, HTTPException, Query
3
+ from typing import Optional
4
+
5
+ # Initialize the FastAPI app
6
+ app = FastAPI(
7
+ title="FastAPI DuckDuckGo Lite Proxy",
8
+ description="A FastAPI proxy for the DuckDuckGo Lite search engine.",
9
+ version="1.0.0",
10
+ )
11
+
12
+ # Define the base URL for the DuckDuckGo Lite API
13
+ DUCKDUCKGO_LITE_URL = "https://lite.duckduckgo.com/lite/"
14
+
15
+ @app.get("/search", tags=["Search"])
16
+ async def search_duckduckgo(
17
+ q: str = Query(..., description="The search query."),
18
+ s: Optional[int] = Query(0, description="Can be `0`."),
19
+ o: Optional[str] = Query("json", description="Set to `json` for JSON output."),
20
+ kl: Optional[str] = Query("wt-wt", description="Region, e.g., us-en, uk-en."),
21
+ bing_market: Optional[str] = Query("wt-wt", description="Bing market region.")
22
+ ):
23
+ """
24
+ Performs a search using the DuckDuckGo Lite API and returns the results.
25
+ """
26
+ params = {
27
+ "q": q,
28
+ "s": s,
29
+ "o": o,
30
+ "kl": kl,
31
+ "bing_market": bing_market,
32
+ }
33
+
34
+ # Use httpx for asynchronous requests
35
+ async with httpx.AsyncClient() as client:
36
  try:
37
+ # The OpenAPI spec indicates a POST, but parameters are in the query.
38
+ # A GET request is more appropriate for a search with query parameters.
39
+ response = await client.get(DUCKDUCKGO_LITE_URL, params=params)
40
+
41
+ # Raise an exception for bad status codes (4xx or 5xx)
42
+ response.raise_for_status()
43
+
44
+ # Return the JSON response from the API
45
+ return response.json()
 
 
 
 
 
 
 
 
 
 
 
46
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47
  except httpx.HTTPStatusError as e:
48
+ raise HTTPException(
49
+ status_code=e.response.status_code,
50
+ detail=f"Error from DuckDuckGo API: {e.response.text}",
51
+ )
52
+ except httpx.RequestError as e:
53
+ raise HTTPException(
54
+ status_code=500,
55
+ detail=f"Failed to connect to DuckDuckGo API: {str(e)}",
56
+ )
57
+
58
+ # Optional: Add a root endpoint for health checks or basic info
59
+ @app.get("/", tags=["Root"])
60
+ async def read_root():
61
+ return {"message": "Welcome to the DuckDuckGo Lite API proxy!"}