1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
|
# This file is part of Senator Sperma
# Licensed under the GPL-3.0 License
# Copyright (C) 2026 Salmonik @ salmonik@tuta.io
# https://codeberg.org/salmonik/senator-sperma
import discord
from discord import Embed
from discord.ext import commands
import requests
from bs4 import BeautifulSoup
import urllib.parse
import yt_dlp
import logging
logger = logging.getLogger(__name__)
class Web(commands.Cog):
def __init__(self, bot):
self.bot = bot
def _extract_youtube_title(self, url):
"""Extract YouTube video title if URL is a YouTube link."""
if "youtube.com/watch" not in url:
return None
logger.info("youtube link")
try:
ydl_opts = {"quiet": True, "nowarnings": True}
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
info = ydl.extract_info(url, download=False)
return info.get("title") if info else None
except Exception:
pass
return None
def _process_search_results(self, links, query):
"""Process search results and create embed."""
embed = Embed(title="Search Results", description=f"Top results for: {query}", color=0x1E90FF)
view = discord.ui.View(disable_on_timeout=True)
for i, link in enumerate(links[:5], start=1):
title = link.text
youtube_title = self._extract_youtube_title(link.get("href"))
if youtube_title:
title = youtube_title
embed.add_field(name=f"Result {i}", value=f"[{title}]({link.get('href')})", inline=False)
return embed, view
@commands.slash_command(
name="web",
description="Search the web using DuckDuckGo"
)
async def web(
self,
ctx: discord.ApplicationContext,
query: str
):
await ctx.defer()
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3"}
encoded_query = urllib.parse.quote_plus(query)
url = f"https://duckduckgo.com/html/?q={encoded_query}"
response = requests.get(url, headers=headers)
logger.info(f"Query: {query}")
if response.status_code != 200:
await ctx.respond(content=f"Error: {response.status_code}", ephemeral=True)
logger.error(f"Error: {response.status_code}")
return
soup = BeautifulSoup(response.text, "html.parser")
links = soup.find_all("a", class_="result__a")
if not links:
await ctx.respond(content="No results found.", ephemeral=True)
logger.warning("No results found")
return
embed, view = self._process_search_results(links, query)
await ctx.respond(embed=embed, view=view)
logger.info("Search results sent")
def setup(bot):
bot.add_cog(Web(bot))
|