Format: text/x-python
⬇ Download File (5.2 KB)
   1  from typing import List, Tuple
   2  import requests
   3  from bs4 import BeautifulSoup
   4  from duckduckgo_search import DDGS
   5  from googlesearch import search as google_search
   6  import arxiv
   7  import logging
   8  from pydantic import ValidationError
   9  import json
  10  import wikipedia
  11  import yfinance as yf
  12  from ..tools.schemas import (
  13      FetchNewsParams,
  14      FetchArxivParams,
  15      FetchDDGParams,
  16      FetchTorrentsParams,
  17      FetchWikiParams,
  18      FetchIMDBParams,
  19      FetchYouTubeParams,
  20      FetchFinanceParams
  21  )
  22  
  23  logging.basicConfig(level=logging.INFO)
  24  logger = logging.getLogger(__name__)
  25  
  26  
  27  # ——— Utility: scrape a page for title + snippet ———
  28  def scrape_page(url: str) -> Tuple[str, str]:
  29      try:
  30          global scrape_counter
  31          resp = requests.get(url, headers={"User-Agent": "Mozilla/5.0"}, timeout=5)
  32          resp.raise_for_status()
  33          soup = BeautifulSoup(resp.text, "html.parser")
  34          title = soup.title.string.strip() if soup.title else url
  35          paragraphs = soup.find_all("p")
  36          snippet = "\n".join(p.get_text().strip() for p in paragraphs)
  37          scrape_id = f"scrape_{scrape_counter}"
  38          scrape_counter += 1
  39          scraped_store[scrape_id] = {"href": url, "text": snippet}
  40          return title, snippet
  41      except Exception:
  42          return url, ""
  43  
  44  # ——— Tool: Google N search ———
  45  def fetch_news(**kwargs) -> List[str]:
  46      try:
  47          params = FetchNewsParams(**kwargs)
  48          results = []
  49          for url in google_search(params.query, num_results=params.max_results, unique=True):
  50              title, snippet = scrape_page(url)
  51              results.append(f"{title}\n{snippet}\n{url}")
  52              # logger.info("Google: %s", f"{title}\n{snippet}\n{url}")
  53              if len(results) >= params.max_results:
  54                  break
  55          return results
  56      except ValidationError as e:
  57          logger.error(f"Invalid parameters: {e}")
  58          return []
  59  
  60  # ——— Tool: arXiv search ———
  61  def fetch_arxiv(**kwargs) -> List[str]:
  62      try:
  63          params = FetchArxivParams(**kwargs)
  64          papers = []
  65          search = arxiv.Search(query=params.query, max_results=params.max_results)
  66          for r in search.results():
  67              summary = r.summary.replace("\n", " ").strip()
  68              papers.append(f"{r.title}\nAbstract: {summary}\nPDF: {r.pdf_url}")
  69          return papers
  70      except ValidationError as e:
  71          logger.error(f"Invalid parameters: {e}")
  72          return []
  73  
  74  # ——— Tool: DuckDuckGo text search ———
  75  def search_google(**kwargs) -> List[str]:
  76      try:
  77          return fetch_news(**kwargs)
  78      except ValidationError as e:
  79          logger.error(f"Invalid parameters: {e}")
  80          return []
  81  
  82  # ——— Tool: Torrent search ———
  83  def fetch_torrents(**kwargs) -> List[str]:
  84      try:
  85          params = FetchTorrentsParams(**kwargs)
  86          return search_google(query=f"""{params.query} proxy "torrent" """, max_results=params.max_results)
  87      except ValidationError as e:
  88          logger.error(f"Invalid parameters: {e}")
  89          return []
  90  
  91  
  92  scraped_store = {}
  93  scrape_counter = 0
  94  
  95  def fetch_wikipedia(**kwargs) -> List[str]:
  96      try:
  97          params = FetchWikiParams(**kwargs)
  98          wikipedia.set_lang("en")
  99          results = []
 100          global scrape_counter
 101          for title in wikipedia.search(params.query, results=params.max_results):
 102              try:
 103                  page = wikipedia.page(title, auto_suggest=False)
 104                  scrape_id = f"scrape_{scrape_counter}"
 105                  scrape_counter += 1
 106                  scraped_store[scrape_id] = {"href": page.url, "text": page.summary}
 107                  results.append(f"{page.title}\n{page.summary}\n{page.url}")
 108              except Exception as e:
 109                  logger.warning(f"Wikipedia subpage error: {e}")
 110          return results
 111      except Exception as e:
 112          logger.error(f"Wikipedia fetch error: {e}")
 113          return []
 114  
 115  def fetch_imdb(**kwargs) -> List[str]:
 116      try:
 117          params = FetchIMDBParams(**kwargs)
 118          return search_google(query=f"{params.query} site:imdb.com", max_results=params.max_results)
 119      except Exception as e:
 120          logger.error(f"IMDB fetch error: {e}")
 121          return []
 122  
 123  def fetch_youtube(**kwargs) -> List[str]:
 124      try:
 125          params = FetchYouTubeParams(**kwargs)
 126          return search_google(query=f"{params.query} site:youtube.com", max_results=params.max_results)
 127      except Exception as e:
 128          logger.error(f"YouTube fetch error: {e}")
 129          return []
 130  
 131  def fetch_finance(**kwargs) -> List[str]:
 132      try:
 133          params = FetchFinanceParams(**kwargs)
 134          results = []
 135          global scrape_counter
 136          tickers = params.query.strip().split()
 137          for symbol in tickers:
 138              ticker = yf.Ticker(symbol)
 139              info = ticker.info
 140              text = info.get("longBusinessSummary") or info.get("summary") or ""
 141              url = f"https://finance.yahoo.com/quote/{symbol}"
 142              scrape_id = f"scrape_{scrape_counter}"
 143              scrape_counter += 1
 144              scraped_store[scrape_id] = {"href": url, "text": text}
 145              results.append(f"{symbol.upper()}\n{text}\n{url}")
 146          return results
 147      except Exception as e:
 148          logger.error(f"Finance fetch error: {e}")
 149          return []
 150