/search repaired

Signed-off-by: ale <ale@manalejandro.com>
This commit is contained in:
ale 2025-06-08 04:37:09 +02:00
parent d3c602df4f
commit ab9fa7fdf3
Signed by: ale
GPG Key ID: 244A9C4DAB1C0C81

332
index.js
View File

@ -256,173 +256,179 @@ async function validateImageUrl(url) {
}
}
// Custom search function as alternative to google-it
// Real search function using DuckDuckGo API for actual search results
async function searchImages(query, limit = 10) {
try {
console.log(`Custom search for: ${query}`);
console.log(`Searching for images: ${query}`);
// Use DuckDuckGo Instant Answer API for real search results
const searchUrl = `https://api.duckduckgo.com/?q=${encodeURIComponent(query + ' image')}&format=json&no_html=1&skip_disambig=1&safe_search=strict`;
const response = await fetch(searchUrl, {
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
}
});
if (!response.ok) {
throw new Error(`Search API failed: ${response.status}`);
}
const data = await response.json();
const searchResults = [];
// Use Dog CEO API - it's reliable and provides direct image URLs
try {
// Get multiple dog images since they always work
const numberOfImages = Math.min(limit, 5);
const promises = [];
for (let i = 0; i < numberOfImages; i++) {
promises.push(
fetch('https://dog.ceo/api/breeds/image/random')
.then(response => response.json())
.then(data => {
if (data.status === 'success') {
return {
title: `${query} - Image ${i + 1}`,
link: data.message
};
}
return null;
})
.catch(() => null)
);
// Extract image results from DuckDuckGo response
if (data.Results && data.Results.length > 0) {
for (let i = 0; i < Math.min(data.Results.length, limit); i++) {
const result = data.Results[i];
if (result.Icon && result.Icon.URL) {
searchResults.push({
title: result.Text || `${query} - Result ${i + 1}`,
link: result.Icon.URL
});
}
}
const results = await Promise.all(promises);
// Add successful results
results.forEach(result => {
if (result) {
searchResults.push(result);
}
});
} catch (error) {
console.log('Dog API failed:', error);
}
// If we don't have enough results, add some static fallback images that are guaranteed to work
if (searchResults.length < limit) {
const fallbackImages = [
{
title: `${query} - Sample Image 1`,
link: `https://images.dog.ceo/breeds/hound-afghan/n02088094_1003.jpg`
},
{
title: `${query} - Sample Image 2`,
link: `https://images.dog.ceo/breeds/terrier-fox/n02095314_2650.jpg`
},
{
title: `${query} - Sample Image 3`,
link: `https://images.dog.ceo/breeds/spaniel-blenheim/n02086646_1061.jpg`
// If no Results, try using Related Topics
if (searchResults.length === 0 && data.RelatedTopics && data.RelatedTopics.length > 0) {
for (let i = 0; i < Math.min(data.RelatedTopics.length, limit); i++) {
const topic = data.RelatedTopics[i];
if (topic.Icon && topic.Icon.URL) {
searchResults.push({
title: topic.Text || `${query} - Topic ${i + 1}`,
link: topic.Icon.URL
});
}
];
const needed = limit - searchResults.length;
searchResults.push(...fallbackImages.slice(0, needed));
}
}
console.log(`Generated ${searchResults.length} reliable image results`);
// If still no results, try scraping Unsplash for real photos
if (searchResults.length === 0) {
try {
const unsplashUrl = `https://unsplash.com/s/photos/${encodeURIComponent(query)}`;
const pageResponse = await fetch(unsplashUrl, {
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
}
});
if (pageResponse.ok) {
const html = await pageResponse.text();
const $ = cheerio.load(html);
// Extract image URLs from Unsplash
$('img[src*="unsplash"]').each((i, element) => {
if (searchResults.length >= limit) return false;
const src = $(element).attr('src');
const alt = $(element).attr('alt') || `${query} - Image ${i + 1}`;
if (src && src.includes('unsplash')) {
searchResults.push({
title: alt,
link: src
});
}
});
}
} catch (unsplashError) {
console.log('Unsplash scraping failed:', unsplashError.message);
}
}
console.log(`Found ${searchResults.length} real search results for: ${query}`);
return searchResults.slice(0, limit);
} catch (error) {
console.error('Custom search failed:', error);
// Ultimate fallback - use known working dog image URLs
return [
{
title: `${query} - Fallback Image 1`,
link: `https://images.dog.ceo/breeds/hound-afghan/n02088094_1003.jpg`
},
{
title: `${query} - Fallback Image 2`,
link: `https://images.dog.ceo/breeds/terrier-fox/n02095314_2650.jpg`
},
{
title: `${query} - Fallback Image 3`,
link: `https://images.dog.ceo/breeds/spaniel-blenheim/n02086646_1061.jpg`
}
];
console.error('Search failed:', error);
throw new Error(`Failed to search for "${query}": ${error.message}`);
}
}
// Custom video search function
// Real video search function using YouTube search
async function searchVideos(query, limit = 5) {
try {
console.log(`Custom video search for: ${query}`);
console.log(`Searching for videos: ${query}`);
// Use DuckDuckGo to search for YouTube videos
const searchUrl = `https://api.duckduckgo.com/?q=${encodeURIComponent(query + ' site:youtube.com')}&format=json&no_html=1&skip_disambig=1`;
const response = await fetch(searchUrl, {
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
}
});
if (!response.ok) {
throw new Error(`Video search API failed: ${response.status}`);
}
const data = await response.json();
const videoResults = [];
// Create themed video results based on the query
const videoThemes = {
'music': [
{
title: `${query} - Music Video Example`,
link: `https://www.youtube.com/watch?v=dQw4w9WgXcQ`,
snippet: `Music video related to: ${query}`
// Extract video results from DuckDuckGo response
if (data.Results && data.Results.length > 0) {
for (let i = 0; i < Math.min(data.Results.length, limit); i++) {
const result = data.Results[i];
if (result.FirstURL && result.FirstURL.includes('youtube.com')) {
videoResults.push({
title: result.Text || `${query} - Video ${i + 1}`,
link: result.FirstURL,
snippet: result.Text || `Video related to: ${query}`
});
}
],
'tutorial': [
{
title: `${query} - Tutorial Video`,
link: `https://www.youtube.com/watch?v=9bZkp7q19f0`,
snippet: `Educational content about: ${query}`
}
],
'tech': [
{
title: `${query} - Technology Overview`,
link: `https://www.youtube.com/watch?v=dQw4w9WgXcQ`,
snippet: `Technology video about: ${query}`
}
],
'coding': [
{
title: `${query} - Programming Tutorial`,
link: `https://www.youtube.com/watch?v=9bZkp7q19f0`,
snippet: `Coding tutorial for: ${query}`
}
]
};
const queryLower = query.toLowerCase();
let foundTheme = false;
// Check if query matches any theme
for (const [theme, videos] of Object.entries(videoThemes)) {
if (queryLower.includes(theme)) {
videoResults.push(...videos);
foundTheme = true;
break;
}
}
// If no theme matched, add generic results
if (!foundTheme) {
videoResults.push(
{
title: `${query} - Video Result 1`,
link: `https://www.youtube.com/watch?v=dQw4w9WgXcQ`,
snippet: `Video content related to: ${query}`
},
{
title: `${query} - Video Result 2`,
link: `https://www.youtube.com/watch?v=9bZkp7q19f0`,
snippet: `Additional video about: ${query}`
// Try scraping YouTube search results if DuckDuckGo doesn't return enough
if (videoResults.length === 0) {
try {
const youtubeSearchUrl = `https://www.youtube.com/results?search_query=${encodeURIComponent(query)}`;
const pageResponse = await fetch(youtubeSearchUrl, {
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
}
});
if (pageResponse.ok) {
const html = await pageResponse.text();
// Extract video IDs from YouTube search results
const videoIdRegex = /"videoId":"([^"]+)"/g;
const titleRegex = /"title":{"runs":\[{"text":"([^"]+)"/g;
let match;
const videoIds = [];
const titles = [];
while ((match = videoIdRegex.exec(html)) !== null && videoIds.length < limit) {
videoIds.push(match[1]);
}
while ((match = titleRegex.exec(html)) !== null && titles.length < limit) {
titles.push(match[1]);
}
for (let i = 0; i < Math.min(videoIds.length, limit); i++) {
videoResults.push({
title: titles[i] || `${query} - Video ${i + 1}`,
link: `https://www.youtube.com/watch?v=${videoIds[i]}`,
snippet: `Video about: ${query}`
});
}
}
);
} catch (youtubeError) {
console.log('YouTube scraping failed:', youtubeError.message);
}
}
console.log(`Generated ${videoResults.length} video results for: ${query}`);
console.log(`Found ${videoResults.length} real video results for: ${query}`);
return videoResults.slice(0, limit);
} catch (error) {
console.error('Video search failed:', error);
return [
{
title: `${query} - Default Video`,
link: `https://www.youtube.com/watch?v=dQw4w9WgXcQ`,
snippet: `Video placeholder for: ${query}`
}
];
throw new Error(`Failed to search videos for "${query}": ${error.message}`);
}
}
@ -638,69 +644,47 @@ client.on(Events.InteractionCreate, async interaction => {
try {
if (mediaType === 'image') {
console.log('Processing image search with custom function...');
console.log('Processing real image search...');
// Use our custom search function
const results = await searchImages(query, count * 2);
console.log(`Custom search returned ${results.length} results`);
// Use real search function
const results = await searchImages(query, count);
console.log(`Real search returned ${results.length} results`);
if (results.length === 0) {
await interaction.editReply(`❌ No image results found for "${query}". Try a different search term.`);
await interaction.editReply(`❌ No image results found for "${query}". The search engines may not have returned any results for this query.`);
return;
}
const imageResults = [];
console.log(`Processing ${results.length} search results...`);
for (const result of results) {
const url = result.link;
// Use more lenient validation for image search results
const validation = await validateImageUrl(url);
if (validation.valid) {
imageResults.push({
title: result.title,
url: url,
contentType: validation.contentType
});
if (imageResults.length >= count) break;
}
}
if (imageResults.length === 0) {
await interaction.editReply(`No valid image results found for "${query}". The search returned results but they couldn't be validated as images.`);
return;
}
// Create embeds for images
const embeds = imageResults.map((result, i) => {
// Create embeds for images (skip validation since we're getting real search results)
const embeds = results.map((result, i) => {
return new EmbedBuilder()
.setTitle(`Image ${i + 1}: ${result.title}`)
.setImage(result.url)
.setTitle(`${result.title}`)
.setImage(result.link)
.setColor(0x00AE86)
.setFooter({ text: `Content-Type: ${result.contentType}` });
.setFooter({ text: `Search result ${i + 1} of ${results.length}` });
});
await interaction.editReply({
content: `Found ${imageResults.length} images for "${query}":`,
content: `🔍 Found ${results.length} images for "${query}":`,
embeds: embeds.slice(0, 10) // Discord allows max 10 embeds
});
}
else if (mediaType === 'video') {
console.log('Processing video search with custom function...');
console.log('Processing real video search...');
// Use our custom video search function
// Use real video search function
const results = await searchVideos(query, count);
console.log(`Custom video search returned ${results.length} results`);
console.log(`Real video search returned ${results.length} results`);
if (results.length === 0) {
await interaction.editReply(`❌ No video results found for "${query}". Try a different search term.`);
await interaction.editReply(`❌ No video results found for "${query}". The search engines may not have returned any results for this query.`);
return;
}
// Create embeds for videos
const embeds = results.map((result, i) => {
const embed = new EmbedBuilder()
.setTitle(`Video ${i + 1}: ${result.title}`)
.setTitle(`${result.title}`)
.setURL(result.link)
.setColor(0xFF0000)
.setDescription(result.snippet || 'No description available');
@ -717,13 +701,13 @@ client.on(Events.InteractionCreate, async interaction => {
});
await interaction.editReply({
content: `Found ${results.length} videos for "${query}":`,
content: `🔍 Found ${results.length} videos for "${query}":`,
embeds: embeds
});
}
} catch (error) {
console.error('Search error:', error);
await interaction.editReply(`Error searching for "${query}": ${error.message}`);
await interaction.editReply(`Error searching for "${query}": ${error.message}\n\nThis could be due to rate limiting or the search service being unavailable.`);
}
break;