async function searchResults(keyword) { try { const encodedKeyword = encodeURIComponent(keyword); const response = await fetchv2(`https://mangakatana.com/?search=${encodedKeyword}&search_by=book_name`); const html = await response.text(); const results = []; const itemRegex = /
]*data-genre="[^"]*"[^>]*data-id="[^"]*"[^>]*>([\s\S]*?)(?=
\s*]*>([^<]+)<\/a>/; const imageRegex = /
\s*]*>Description<\/div>\s*

([\s\S]*?)<\/p>/); let description = 'No description available'; if (descMatch && descMatch[1]) { description = descMatch[1] .replace(/<[^>]+>/g, '') .replace(/\s+/g, ' ') .trim(); } const transformedResults = [{ description, aliases: 'N/A', airdate: 'N/A' }]; console.log(`Details for "${url}":`, JSON.stringify(transformedResults)); return JSON.stringify(transformedResults); } catch (error) { console.log('Details error:', error); return JSON.stringify([{ description: 'Error loading description', aliases: 'N/A', airdate: 'N/A' }]); } } async function extractChapters(url) { try { const response = await soraFetch(url); const htmlText = await response.text(); const chapterRegex = /[\s\S]*?([\s\S]*?)<\/a>[\s\S]*?<\/tr>/g; const chapters = []; let match; while ((match = chapterRegex.exec(htmlText)) !== null) { const href = match[1].trim(); const titleMatch = /Chapter \d+[:\s]?.*/i.exec(match[2]); const title = titleMatch ? decodeHtmlEntities(titleMatch[0].trim()) : "Unknown Chapter"; const numberMatch = /Chapter (\d+)/i.exec(title); const number = numberMatch ? parseInt(numberMatch[1]) : NaN; chapters.push({ number: number === 0 ? 1 : number, href: href.startsWith("http") ? href : "https://mangakatana.com" + href, title: title }); } chapters.reverse(); console.log(JSON.stringify(chapters)); return chapters; } catch (error) { console.error('Fetch error in extractChapters:', error); return []; } } async function extractText(url) { try { const response = await soraFetch(url); const htmlText = await response.text(); const testUrl = 'https://static.wikia.nocookie.net/473b884a-a6d8-43ad-9c9c-fa6b676f8126'; const imageUrls = Array(20).fill(testUrl); const html = ` Manga ${imageUrls.map((url, i) => `

Image ${i+1}
`).join('\n')} `; return html; } catch (error) { console.error("❌ Error in extractImages:", error); return { error: `Error loading chapter images: ${error.message}` }; } } function decodeHtmlEntities(str) { const named = { amp: '&', lt: '<', gt: '>', quot: '"', apos: "'", nbsp: ' ', hellip: '…', rsquo: '’', lsquo: '‘', ndash: '–', mdash: '—' }; return str .replace(/&([a-z]+);/gi, (match, name) => named[name] || match) .replace(/&#(\d+);/g, (_, code) => String.fromCharCode(code)); } async function soraFetch(url, options = { headers: {}, method: 'GET', body: null }) { try { return await fetchv2(url, options.headers ?? {}, options.method ?? 'GET', options.body ?? null); } catch(e) { try { return await fetch(url, options); } catch(error) { return null; } } }