home chevron_right src chevron_right pixiv.js
code

pixiv.js

JavaScript 14.43 KB 521 baris visibility 17 views
open_in_new
src/pixiv.js
// ======== CMJS ========
const axios =  require("axios")

// ========= Esm ==========
// import axios from 'axios';

// =========== Esm - cmjs ==========
// import { createRequire } from 'module';
// const require = createRequire(import.meta.url);
// const axios = require("axios")



> Ini Versi Pixiv Yang Udah Lengkap Ku Perdetail lagi sama ada beberap perubah dari Versi Sebelumnya Di Buat Jadi Lebih Lengkap Tentunya Bisa Kalian Set Cookie ya! 
> *Refactored code By:* _*Bobby Ajah*_


const baseRes = {
  author_skrep: 'JH a.k.a Dhika',
  kesayangan: 'Fiony Alveriaβ™‘', 
  refactored_by: 'Bobby Ajah'
};

const headers = {
  'Accept': 'application/json',
  'Accept-Language': 'id-ID,id;q=0.9,en-US;q=0.8,en;q=0.7',
  // Cookie Opsional Kalau Mau Ngambil search pixiv semua media termasuk yang ada nsfwnya/r18 pake cookie ya. pastikan di akunnya udh di aktifkan r18 nya di settings akunya.
  'Cookie': '', 
  'Origin': 'https://www.pixiv.net',
  'Sec-Ch-Ua': '"Chromium";v="137", "Not/A)Brand";v="24"',
  'Sec-Ch-Ua-Mobile': '?0',
  'Sec-Ch-Ua-Platform': '"Windows"',
  'Sec-Fetch-Dest': 'empty',
  'Sec-Fetch-Mode': 'cors',
  'Sec-Fetch-Site': 'same-origin',
  'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36'
};

// Helper
function parseTags(tags = []) {
  return tags.map(tag => ({
    tag: tag.tag || null,
    romaji: tag.romaji || null,
    translation:
      tag.translation?.en ||
      tag.translation ||
      null
  }));
}

function parsePages(manga = []) {
  return manga.map(v => ({
    page: v.page,
    preview: v.url,
    small: v.url_small,
    original: v.url_big
  }));
}

// Search
async function pixivSearch(query, page = 1) {
  try {
    if (!query) {
      throw new Error('Query search gak boleh kosong wak!');
    }
    page = Number(page) || 1;
    if (page < 1) {
      page = 1;
    }
    headers['Referer'] = `https://www.pixiv.net/en/tags/${encodeURIComponent(query)}/artworks`;
    const firstUrl = `https://www.pixiv.net/ajax/search/artworks/${encodeURIComponent(query)}?word=${encodeURIComponent(query)}&order=date_d&mode=all&p=1&s_mode=s_tag&type=all&lang=en`;
    const { data: firstData } = await axios.get(firstUrl, { headers });
    if (firstData.error) {
      throw new Error(firstData.message || 'Error dari API Pixiv!');
    }
    const maxPage =
      firstData.body?.illustManga?.lastPage || 1;
    if (page > maxPage) {
      page = maxPage;
    }
    const finalUrl = `https://www.pixiv.net/ajax/search/artworks/${encodeURIComponent(query)}?word=${encodeURIComponent(query)}&order=date_d&mode=all&p=${page}&s_mode=s_tag&type=all&lang=en`;
    const { data } = await axios.get(finalUrl, { headers });
    if (data.error) {
      throw new Error(data.message || 'Error dari API Pixiv!');
    }
    const body = data.body || {};
    const illust = body.illustManga || {};
    const results = (illust.data || [])
      .filter(v => v.id)
      .map(v => ({
        id: v.id,
        title: v.title,
        type:
          v.illustType === 0 ? 'Illustration' :
          v.illustType === 1 ? 'Manga' :
          v.illustType === 2 ? 'Ugoira' :
          'Unknown',
        illust_type: v.illustType,
        author: {
          id: v.userId,
          name: v.userName,
          profile_picture: v.profileImageUrl
        },
        image: {
          thumbnail: v.url,
          width: v.width,
          height: v.height,
          ratio: `${v.width}x${v.height}`
        },
        page_count: v.pageCount,
        tags: v.tags || [],
        caption: v.alt || '',
        description: v.description || '',
        create_date: v.createDate,
        update_date: v.updateDate,
        ai_type:
          v.aiType === 0 ? 'Unknown' :
          v.aiType === 1 ? 'AI Assisted' :
          v.aiType === 2 ? 'AI Generated' :
          'Unknown',
        x_restrict: v.xRestrict,
        restrict: v.restrict,
        is_r18: v.xRestrict === 1,
        is_bookmarkable: v.isBookmarkable,
        bookmark_data: v.bookmarkData,
        is_original: v.isOriginal,
        is_unlisted: v.isUnlisted,
        is_masked: v.isMasked,
        is_howto: v.is_howto,
        visibility_scope: v.visibilityScope,
        title_caption_translation:
          v.titleCaptionTranslation || {}
      }));
    const resultsNah = {
      ...baseRes,
      status: true,
      type: 'search',
      query,
      current_page: page,
      max_page: maxPage,
      total: illust.total || 0,
      total_result: results.length,
      related_tags:
        body.relatedTags || [],
      tag_translation:
        body.tagTranslation || {},
      data: results
    }
    return resultsNah
  } catch (e) {
    let err = e.response?.data || e.message;
    if (Buffer.isBuffer(err)) {
      err = err.toString('utf-8');
    }
    return {
      ...baseRes,
      status: false,
      error: err
    }
  }
}

// Detail
async function pixivDetail(id) {
  try {
    if (!id) {
      throw new Error('ID artwork wajib diisi wak!');
    }
    headers['Referer'] = `https://www.pixiv.net/en/artworks/${id}`;
    const { data: detailData } = await axios.get(`https://www.pixiv.net/ajax/illust/${id}`, { headers });
    if (detailData.error) {
      throw new Error(
        detailData.message || 'Gagal narik detail!'
      );
    }
    const info = detailData.body || {};
    const touchUrl = `https://www.pixiv.net/touch/ajax/illust/details?illust_id=${id}&ref=&lang=en&version=60714fe62bb4943c447667fb6a4f9eef6d4edeaa`;
    const { data: touchData } = await axios.get(touchUrl, { headers });
    if (touchData.error) {
      throw new Error(
        touchData.message || 'Gagal narik raw detail!'
      );
    }
    const detail = touchData.body?.illust_details || {};
    const mangaPages = parsePages(detail.manga_a || []);
    const resultsNah = {
      ...baseRes,
      status: true,
      type: 'detail',
      data: {
        id:
          detail.id || info.illustId,
        title:
          detail.title || info.illustTitle,
        description:
          detail.comment || '',
        share_text:
          detail.share_text || null,
        type:
          info.illustType === 0 ? 'Illustration' :
          info.illustType === 1 ? 'Manga' :
          info.illustType === 2 ? 'Ugoira' :
          'Unknown',
        illust_type:
          info.illustType,
        author: {
          id:
            detail.author_details?.user_id ||
            info.userId,
          name:
            detail.author_details?.user_name ||
            info.userName,
          account:
            detail.author_details?.user_account ||
            null,
          profile_picture:
            touchData.body?.author_details?.profile_img?.main ||
            null
        },
        image: {
          preview:
            detail.url || null,
          thumbnail:
            detail.url_s || null,
          square:
            detail.url_ss || null,
          placeholder:
            detail.url_placeholder || null,
          original:
            detail.url_big || null
        },
        pages:
          mangaPages,
        total_pages:
          mangaPages.length,
        dimensions: {
          width:
            Number(detail.width || info.width),
          height:
            Number(detail.height || info.height),
          ratio:
            `${detail.width || info.width}x${detail.height || info.height}`
        },
        stats: {
          views:
            Number(detail.rating_view || info.viewCount || 0),
          bookmarks:
            Number(detail.bookmark_user_total || info.bookmarkCount || 0),
          likes:
            Number(info.likeCount || 0),
          comments:
            Number(detail.rating_count || info.commentCount || 0)
        },
        tags:
          parseTags(detail.display_tags || []),
        raw_tags:
          detail.tags || [],
        page_count:
          Number(detail.page_count || info.pageCount || 1),
        restrict:
          Number(detail.restrict || 0),
        x_restrict:
          Number(detail.x_restrict || 0),
        is_r18:
          Number(detail.x_restrict || 0) === 1,
        is_original:
          detail.is_original || false,
        ai_type:
          detail.ai_type || 0,
        upload_timestamp:
          detail.upload_timestamp || null,
        upload_date:
          detail.upload_timestamp
            ? new Date(detail.upload_timestamp * 1000).toISOString()
            : null,
        create_date:
          info.createDate || null,
        upload_date_full:
          info.uploadDate || null,
        title_caption_translation:
          detail.title_caption_translation || {},
      }
    }
    return resultsNah
  } catch (e) {
    let err = e.response?.data || e.message;
    if (Buffer.isBuffer(err)) {
      err = err.toString('utf-8');
    }
    return {
      ...baseRes,
      status: false,
      error: err
    }
  }
}

// Download
async function pixivDownload(url) {
  try {
    if (!url) {
      throw new Error(
        'URL gambar wajib diisi wak!'
      );
    }
    headers['Referer'] = 'https://www.pixiv.net/';
    const { data, headers: resHeaders } = await axios.get(url, {
      headers,
      responseType: 'arraybuffer'
    });
    return {
      ...baseRes,
      status: true,
      type: 'download',
      data: {
        mime:
          resHeaders['content-type'] ||
          'image/jpeg',
        size:
          Buffer.byteLength(data),
        buffer:
          Buffer.from(data)
      }
    };
  } catch (e) {
    let err = e.response?.data || e.message;
    if (Buffer.isBuffer(err)) {
      err = err.toString('utf-8');
    }
    return {
      ...baseRes,
      status: false,
      error: err
    }
  }
}

// Author
async function pixivAuthor(authorId) {
  try {
    if (!authorId) {
      throw new Error(
        'ID Author wajib diisi wak!'
      );
    }
    headers['Referer'] = `https://www.pixiv.net/en/users/${authorId}`;
    // ===== PROFILE ALL =====
    const { data: authorData } = await axios.get(`https://www.pixiv.net/ajax/user/${authorId}/profile/all`, { headers });
    if (authorData.error) {
      throw new Error(
        authorData.message ||
        'Gagal narik profile!'
      );
    }
    // ===== TOUCH DETAIL =====
    const detailUrl = `https://www.pixiv.net/touch/ajax/user/details?id=${authorId}&lang=en&version=689bdfbbc5bda11acacc0952055721d8a78e51fd`;
    const { data: touchData } = await axios.get(detailUrl, { headers });
    if (touchData.error) {
      throw new Error(
        touchData.message ||
        'Gagal narik detail author!'
      );
    }
    const user =
      touchData.body?.user_details || {};
    // ===== WORK IDS =====
    const combinedIds = [
      ...Object.keys(
        authorData.body?.illusts || {}
      ),
      ...Object.keys(
        authorData.body?.manga || {}
      )
    ]
      .sort((a, b) => b - a)
      .slice(0, 15);
    if (!combinedIds.length) {
      return JSON.stringify({
        ...baseRes,
        status: false,
        message: 'Gak ada karya wak!'
      }, null, 2);
    }
    // ===== WORK DETAIL =====
    const idsQuery = combinedIds.map(id => `ids%5B%5D=${id}`).join('&');
    const { data: worksData } = await axios.get(`https://www.pixiv.net/ajax/user/${authorId}/profile/illusts?${idsQuery}&work_category=illustManga&is_first_page=1`, { headers });
    const results = combinedIds
      .map(id => {
        const work =
          worksData.body?.works?.[id];
        if (!work) return null;
        return {
          id: work.id,
          title: work.title,
          type:
            work.illustType === 0 ? 'Illustration' :
            work.illustType === 1 ? 'Manga' :
            work.illustType === 2 ? 'Ugoira' :
            'Unknown',
          illust_type:
            work.illustType,
          thumbnail:
            work.url,
          tags:
            work.tags || [],
          page_count:
            work.pageCount,
          dimensions: {
            width:
              work.width,
            height:
              work.height,
            ratio:
              `${work.width}x${work.height}`
          },
          stats: {
            total_bookmark:
              work.bookmarkCount || 0,
            total_view:
              work.viewCount || 0
          },
          restrict:
            work.xRestrict || 0,
          is_r18:
            work.tags?.includes('R-18') || false
        };
      })
      .filter(Boolean);
    const resultsNah = {
      ...baseRes,
      status: true,
      type: 'author',
      author: {
        id:
          user.user_id || authorId,
        name:
          user.user_name || null,
        account:
          user.user_account || null,
        premium:
          Number(user.user_premium || 0) === 1,
        comment:
          user.user_comment || null,
        comment_html:
          user.user_comment_html || null,
        webpage:
          user.user_webpage || null,
        avatar: {
          main:
            user.profile_img?.main || null,
          small:
            user.profile_img?.main_s || null
        },
        cover_image:
          user.cover_image
            ?.profile_cover_image?.['720x360'] || null,
        social:
          user.social || {},
        commission:
          user.commission || {},
        follows:
          Number(user.follows || 0),
        flags: {
          followed:
            user.is_followed || false,
          following:
            user.is_following || false,
          mypixiv:
            user.is_mypixiv || false,
          blocking:
            user.is_blocking || false,
          blocked:
            user.is_blocked || false,
          official:
            user.is_official || false,
          publisher:
            user.is_publisher || false
        },
        availability: {
          has_illusts:
            user.has_illusts || false,
          has_mangas:
            user.has_mangas || false,
          has_novels:
            user.has_novels || false,
          has_bookmarks:
            user.has_bookmarks || false,
          has_collections:
            user.has_collections || false
        }
      },
      total:
        results.length,
      data:
        results
    }
    return resultsNah
  } catch (e) {
    let err = e.response?.data || e.message;
    if (Buffer.isBuffer(err)) {
      err = err.toString('utf-8');
    }
    return {
      ...baseRes,
      status: false,
      error: err
    }
  }
}

// Beberapa Example Cobain aja Satu Satu πŸ˜…

// SEARCH
// pixivSearch('Hatsune Miku')
// pixivSearch('Hatsune Miku', 5)
// DETAIL
// pixivDetail('98079929')
// DOWNLOAD
// pixivDownload('https://i.pximg.net/img-original/img/2022/05/03/22/46/41/98079929_p0.jpg')
// AUTHOR
// pixivAuthor('38819785')
link

Direct URL

check Disalin!