const axios = require('axios'); class KomikIndo { constructor() { this.client = axios.create({ baseURL: 'https://kmkindo.click', headers: { 'user-agent': 'Dalvik/2.1.0 (Linux; U; Android 10; Redmi Note 4 Build/QQ3A.200905.001)', host: 'kmkindo.click', connection: 'Keep-Alive', 'accept-encoding': 'gzip' } }); this.kmkRegex = /^https?:\/\/kmkindo\.click\/?\?.*?page=(manga|chapter).*?id=(\d+)/; } homepage = async function (type, page = '1') { const _type = ['latest', 'rekomendasi', 'terpopuler']; if (!_type.includes(type)) throw new Error(`List available types: ${_type.join(', ')}`); if (type === 'latest' && page && isNaN(page)) throw new Error('Invalid page input'); const { data } = await this.client(`?page=${type}${type === 'latest' ? `&paged=${page}` : ''}`) .catch(error => { throw new Error(error.message); }); return data; } search = async function (query, page = '1') { if (!query) throw new Error('Query is required'); if (page && isNaN(page)) throw new Error('Invalid page input'); const { data } = await this.client(`?page=search&search=${query}&paged=${page}`) .catch(error => { throw new Error(error.message); }); return data; } genre = async function (genre, page = '1') { const _genre = ['action', 'adventure', 'comedy', 'crime', 'drama', 'fantasy', 'historical', 'horror', 'isekai', 'mecha', 'medical', 'music', 'mystery', 'psychological', 'romance', 'sci-fi', 'shoujo-ai', 'shounen-ai', 'slice-of-life', 'sports', 'thriller', 'tragedy', 'wuxia', 'yuri']; if (!_genre.includes(genre)) throw new Error(`List available genres: ${_genre.join(', ')}`); if (page && isNaN(page)) throw new Error('Invalid page input'); const { data } = await this.client(`?page=term_result&term=genres&val=${genre}&paged=${page}`) .catch(error => { throw new Error(error.message); }); return data; } demographic = async function (dg, page = '1') { const _dg = ['josei', 'seinen', 'shoujo', 'shounen']; if (!_dg.includes(dg)) throw new Error(`List available demographics: ${_dg.join(', ')}`); if (page && isNaN(page)) throw new Error('Invalid page input'); const { data } = await this.client(`?page=term_result&term=demographic&val=${dg}&paged=${page}`) .catch(error => { throw new Error(error.message); }); return data; } theme = async function (th, page = '1') { const _th = ['aliens', 'animals', 'cooking', 'crossdressing', 'delinquents', 'demons', 'genderswap', 'ghosts', 'gyaru', 'harem', 'incest', 'loli', 'mafia', 'magic', 'martial-arts', 'military', 'monster-girls', 'monsters', 'music', 'ninja', 'office-workers', 'police', 'post-apocalyptic', 'reincarnation', 'reverse-harem', 'samurai', 'school-life', 'shota', 'supernatural', 'survival', 'time-travel', 'traditional-games', 'vampires', 'video-games', 'villainess', 'virtual-reality', 'zombies']; if (!_th.includes(th)) throw new Error(`List available themes: ${_th.join(', ')}`); if (page && isNaN(page)) throw new Error('Invalid page input'); const { data } = await this.client(`?page=term_result&term=theme&val=${th}&paged=${page}`) .catch(error => { throw new Error(error.message); }); return data; } content = async function (ct, page = '1') { const _ct = ['ecchi', 'gore', 'sexual-violence', 'smut']; if (!_ct.includes(ct)) throw new Error(`List available contents: ${_ct.join(', ')}`); if (page && isNaN(page)) throw new Error('Invalid page input'); const { data } = await this.client(`?page=term_result&term=content&val=${ct}&paged=${page}`) .catch(error => { throw new Error(error.message); }); return data; } type = async function (ty, page = '1') { const _ty = ['manga', 'manhua', 'manhwa', 'colorized', 'bnw']; if (!_ty.includes(ty)) throw new Error(`List available types: ${_ty.join(', ')}`); if (page && isNaN(page)) throw new Error('Invalid page input'); const { data } = await this.client(`${ty === 'colorized' || ty === 'bnw' ? `?page=colorized&colorized=${ty === 'colorized' ? '1' : '0'}&paged=${page}` : `?page=type&type=${ty}&paged=${page}`}`) .catch(error => { throw new Error(error.message); }); return data; } detail = async function (url) { const match = url.match(this.kmkRegex); if (!url || !match) throw new Error('Invalid url'); const [, page, id] = match; if (page !== 'manga') throw new Error('Invalid url'); const { data } = await this.client(`?page=manga&id=${id}`) .catch(error => { throw new Error(error.message); }); return data; } getImage = async function (url) { const match = url.match(this.kmkRegex); if (!url || !match) throw new Error('Invalid url'); const [, page, id] = match; if (page !== 'chapter') throw new Error('Invalid url'); const { data } = await this.client(`?page=chapter&id=${id}`) .catch(error => { throw new Error(error.message); }); return data; } } // Usage: const k = new KomikIndo(); const resp = await k.detail('https://kmkindo.click/?page=manga&id=313259'); console.log(resp);