/search repaired
Signed-off-by: ale <ale@manalejandro.com>
This commit is contained in:
parent
d3c602df4f
commit
ab9fa7fdf3
330
index.js
330
index.js
@ -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}`);
|
||||
|
||||
const searchResults = [];
|
||||
// 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`;
|
||||
|
||||
// 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)
|
||||
);
|
||||
}
|
||||
|
||||
const results = await Promise.all(promises);
|
||||
|
||||
// Add successful results
|
||||
results.forEach(result => {
|
||||
if (result) {
|
||||
searchResults.push(result);
|
||||
const response = await fetch(searchUrl, {
|
||||
headers: {
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
|
||||
}
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.log('Dog API failed:', error);
|
||||
if (!response.ok) {
|
||||
throw new Error(`Search API failed: ${response.status}`);
|
||||
}
|
||||
|
||||
// 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`
|
||||
}
|
||||
];
|
||||
const data = await response.json();
|
||||
const searchResults = [];
|
||||
|
||||
const needed = limit - searchResults.length;
|
||||
searchResults.push(...fallbackImages.slice(0, needed));
|
||||
// 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
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`Generated ${searchResults.length} reliable image results`);
|
||||
// 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
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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]);
|
||||
}
|
||||
|
||||
console.log(`Generated ${videoResults.length} video results for: ${query}`);
|
||||
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(`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;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user