/search repaired
Signed-off-by: ale <ale@manalejandro.com>
This commit is contained in:
parent
d3c602df4f
commit
ab9fa7fdf3
332
index.js
332
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) {
|
async function searchImages(query, limit = 10) {
|
||||||
try {
|
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 = [];
|
const searchResults = [];
|
||||||
|
|
||||||
// Use Dog CEO API - it's reliable and provides direct image URLs
|
// Extract image results from DuckDuckGo response
|
||||||
try {
|
if (data.Results && data.Results.length > 0) {
|
||||||
// Get multiple dog images since they always work
|
for (let i = 0; i < Math.min(data.Results.length, limit); i++) {
|
||||||
const numberOfImages = Math.min(limit, 5);
|
const result = data.Results[i];
|
||||||
const promises = [];
|
if (result.Icon && result.Icon.URL) {
|
||||||
|
searchResults.push({
|
||||||
for (let i = 0; i < numberOfImages; i++) {
|
title: result.Text || `${query} - Result ${i + 1}`,
|
||||||
promises.push(
|
link: result.Icon.URL
|
||||||
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);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
} 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 no Results, try using Related Topics
|
||||||
if (searchResults.length < limit) {
|
if (searchResults.length === 0 && data.RelatedTopics && data.RelatedTopics.length > 0) {
|
||||||
const fallbackImages = [
|
for (let i = 0; i < Math.min(data.RelatedTopics.length, limit); i++) {
|
||||||
{
|
const topic = data.RelatedTopics[i];
|
||||||
title: `${query} - Sample Image 1`,
|
if (topic.Icon && topic.Icon.URL) {
|
||||||
link: `https://images.dog.ceo/breeds/hound-afghan/n02088094_1003.jpg`
|
searchResults.push({
|
||||||
},
|
title: topic.Text || `${query} - Topic ${i + 1}`,
|
||||||
{
|
link: topic.Icon.URL
|
||||||
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 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);
|
return searchResults.slice(0, limit);
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Custom search failed:', error);
|
console.error('Search failed:', error);
|
||||||
|
throw new Error(`Failed to search for "${query}": ${error.message}`);
|
||||||
// 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`
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Custom video search function
|
// Real video search function using YouTube search
|
||||||
async function searchVideos(query, limit = 5) {
|
async function searchVideos(query, limit = 5) {
|
||||||
try {
|
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 = [];
|
const videoResults = [];
|
||||||
|
|
||||||
// Create themed video results based on the query
|
// Extract video results from DuckDuckGo response
|
||||||
const videoThemes = {
|
if (data.Results && data.Results.length > 0) {
|
||||||
'music': [
|
for (let i = 0; i < Math.min(data.Results.length, limit); i++) {
|
||||||
{
|
const result = data.Results[i];
|
||||||
title: `${query} - Music Video Example`,
|
if (result.FirstURL && result.FirstURL.includes('youtube.com')) {
|
||||||
link: `https://www.youtube.com/watch?v=dQw4w9WgXcQ`,
|
videoResults.push({
|
||||||
snippet: `Music video related to: ${query}`
|
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
|
// Try scraping YouTube search results if DuckDuckGo doesn't return enough
|
||||||
if (!foundTheme) {
|
if (videoResults.length === 0) {
|
||||||
videoResults.push(
|
try {
|
||||||
{
|
const youtubeSearchUrl = `https://www.youtube.com/results?search_query=${encodeURIComponent(query)}`;
|
||||||
title: `${query} - Video Result 1`,
|
const pageResponse = await fetch(youtubeSearchUrl, {
|
||||||
link: `https://www.youtube.com/watch?v=dQw4w9WgXcQ`,
|
headers: {
|
||||||
snippet: `Video content related to: ${query}`
|
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
|
||||||
},
|
}
|
||||||
{
|
});
|
||||||
title: `${query} - Video Result 2`,
|
|
||||||
link: `https://www.youtube.com/watch?v=9bZkp7q19f0`,
|
if (pageResponse.ok) {
|
||||||
snippet: `Additional video about: ${query}`
|
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);
|
return videoResults.slice(0, limit);
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Video search failed:', error);
|
console.error('Video search failed:', error);
|
||||||
return [
|
throw new Error(`Failed to search videos for "${query}": ${error.message}`);
|
||||||
{
|
|
||||||
title: `${query} - Default Video`,
|
|
||||||
link: `https://www.youtube.com/watch?v=dQw4w9WgXcQ`,
|
|
||||||
snippet: `Video placeholder for: ${query}`
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -638,69 +644,47 @@ client.on(Events.InteractionCreate, async interaction => {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
if (mediaType === 'image') {
|
if (mediaType === 'image') {
|
||||||
console.log('Processing image search with custom function...');
|
console.log('Processing real image search...');
|
||||||
|
|
||||||
// Use our custom search function
|
// Use real search function
|
||||||
const results = await searchImages(query, count * 2);
|
const results = await searchImages(query, count);
|
||||||
console.log(`Custom search returned ${results.length} results`);
|
console.log(`Real search returned ${results.length} results`);
|
||||||
|
|
||||||
if (results.length === 0) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const imageResults = [];
|
// Create embeds for images (skip validation since we're getting real search results)
|
||||||
console.log(`Processing ${results.length} search results...`);
|
const embeds = results.map((result, i) => {
|
||||||
|
|
||||||
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) => {
|
|
||||||
return new EmbedBuilder()
|
return new EmbedBuilder()
|
||||||
.setTitle(`Image ${i + 1}: ${result.title}`)
|
.setTitle(`${result.title}`)
|
||||||
.setImage(result.url)
|
.setImage(result.link)
|
||||||
.setColor(0x00AE86)
|
.setColor(0x00AE86)
|
||||||
.setFooter({ text: `Content-Type: ${result.contentType}` });
|
.setFooter({ text: `Search result ${i + 1} of ${results.length}` });
|
||||||
});
|
});
|
||||||
|
|
||||||
await interaction.editReply({
|
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
|
embeds: embeds.slice(0, 10) // Discord allows max 10 embeds
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else if (mediaType === 'video') {
|
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);
|
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) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create embeds for videos
|
// Create embeds for videos
|
||||||
const embeds = results.map((result, i) => {
|
const embeds = results.map((result, i) => {
|
||||||
const embed = new EmbedBuilder()
|
const embed = new EmbedBuilder()
|
||||||
.setTitle(`Video ${i + 1}: ${result.title}`)
|
.setTitle(`${result.title}`)
|
||||||
.setURL(result.link)
|
.setURL(result.link)
|
||||||
.setColor(0xFF0000)
|
.setColor(0xFF0000)
|
||||||
.setDescription(result.snippet || 'No description available');
|
.setDescription(result.snippet || 'No description available');
|
||||||
@ -717,13 +701,13 @@ client.on(Events.InteractionCreate, async interaction => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
await interaction.editReply({
|
await interaction.editReply({
|
||||||
content: `Found ${results.length} videos for "${query}":`,
|
content: `🔍 Found ${results.length} videos for "${query}":`,
|
||||||
embeds: embeds
|
embeds: embeds
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Search error:', 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;
|
break;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user