npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@l2studio/picacomic-api

v0.2.1

Published

A library for PicaComic http web api

Downloads

45

Readme

L2 Studio - PicaComic API

A library for PicaComic http web api

Install

npm install --save @l2studio/picacomic-api
# or
pnpm i @l2studio/picacomic-api

API

Currently the API documentation for version 0.2.x. See also old documentation.

The v0.2.x is a breaking update, but more specific to type definitions. and code refactoring and optimization.

import { PicaComicAPI } from '@l2studio/picacomic-api'

class PicaComicAPI {
  public readonly fetch: Got
  public readonly appOptions?: Partial<PicaComicOptions>
  public readonly reauthorizationTokenCallback?: (self: this) => string | undefined | Promise<string | undefined>
  constructor (options?: PicaComicAPIOptions)
}

API Options

interface PicaComicOptions {
  api: string
  apiKey: string
  signatureKey: string
  accept: string
  channel: '1' | '2' | '3'
  version: string
  uuid: string
  platform: string
  buildVersion: string
  userAgent: string
  imageQuality: 'original' | 'low' | 'medium' | 'high'
}

interface PicaComicAPIOptions {
  // Got instance or options (optional)
  // See: https://github.com/sindresorhus/got/tree/v11
  fetch?: Got | ExtendOptions

  // PicaComic app client options (optional)
  // See above: PicaComicOptions
  appOptions?: Partial<PicaComicOptions>

  // Callback function used to re-authenticate and return a new token when the token is invalid. (optional)
  // Example:
  //   async reauthorizationTokenCallback (self) {
  //     console.log('Token invalid, re-authenticate...')
  //     const response = await self.signIn({
  //       email   : 'your picacomic account email',
  //       password: 'your picacomic account password'
  //     })
  //     return response.data.token
  //   }
  reauthorizationTokenCallback?: (self: PicaComicAPI) => string | undefined | Promise<string | undefined>
}

PicaComicError

class PicaComicError extends Error {
  readonly code: number
  readonly error: string
  readonly message: string
  readonly detail?: string
}

.register

/**
 * Register a PicaComic account with the given payload.
 *
 * @param payload - RegisterPayload {
 *   name      - Nickname (2 - 50 characters)
 *   email     - Email (Allow: [0-9 a-z . _])
 *   password  - Password (Greater than 8 characters)
 *   question1 - Security Question 1
 *   question2 -                   2
 *   question3 -                   3
 *   answer1   - Security question 1 answer
 *   answer2   -                   2 answer
 *   answer3   -                   3 answer
 *   birthday  - Birthday ('YYYY-MM-DD' | Date | Milliseconds) Need to be 18 years or older
 *   gender    - Gender ('m' | 'f' | 'bot')
 * }
 * @return BaseResponse<undefined>
 */
PicaComicAPI.register(payload: RegisterPayload): Promise<BaseResponse<undefined>>

.signIn

/**
 * Sign in to the PicaComic account with the given payload.
 *
 * @param payload - SignInPayload {
 *   email    - Your PicaComic account email
 *   password -                        password
 * }
 * @return SignInResponse
 */
PicaComicAPI.signIn(payload: SignInPayload): Promise<SignInResponse>

.punchIn

/**
 * Punch in to the PicaComic account with the given payload.
 *
 * @param payload - AuthorizationPayload { token - Access token }
 * @return PunchInResponse
 */
PicaComicAPI.punchIn(payload: AuthorizationPayload): Promise<PunchInResponse>

.fetchUserProfile

/**
 * Fetch user profile using the given payload.
 *
 * @param payload - AuthorizationPayload { token - Access token }
 * @return UserProfileResponse
 */
PicaComicAPI.fetchUserProfile(payload: AuthorizationPayload): Promise<UserProfileResponse>

.fetchUserFavourite

/**
 * Fetch user favourite comics using the given payload.
 *
 * @param payload - AuthorizationPayload & UserFavouritePayload {
 *   token - Access token
 *   page  - Page number (optional)
 *   sort  - Sorting type (optional)
 * }
 * @return UserFavouriteResponse
 */
PicaComicAPI.fetchUserFavourite(payload: AuthorizationPayload & UserFavouritePayload): Promise<UserFavouriteResponse>

.fetchCategories

/**
 * Fetch all categories using the given payload.
 *
 * @param payload - AuthorizationPayload { token - Access token }
 * @return CategoriesResponse
 */
PicaComicAPI.fetchCategories(payload: AuthorizationPayload): Promise<CategoriesResponse>

.fetchComics

/**
 * Fetch comics using the given payload.
 *
 * @param payload -  AuthorizationPayload & ComicsPayload {
 *   token    - Access token
 *   category - Specify category name (e.g.: 'Cosplay')
 *   page     - Page number (optional)
 *   sort     - Sorting type (optional)
 * }
 * @return ComicsResponse
 */
PicaComicAPI.fetchComics(payload: AuthorizationPayload & ComicsPayload): Promise<ComicsResponse>

.fetchComicDetail

/**
 * Fetch comic detail using the given payload.
 *
 * @param payload - AuthorizationPayload & ComicDetailPayload {
 *   token   - Access token
 *   comicId - Specify comic id
 * }
 * @return ComicDetailResponse
 */
PicaComicAPI.fetchComicDetail(payload: AuthorizationPayload & ComicDetailPayload): Promise<ComicDetailResponse>

.fetchComicEpisodes

/**
 * Fetch comic episodes using the given payload.
 *
 * @param payload - AuthorizationPayload & ComicEpisodesPayload {
 *   token   - Access token
 *   comicId - Specify comic id
 *   page    - Page number (optional)
 * }
 * @return ComicEpisodesResponse
 */
PicaComicAPI.fetchComicEpisodes(payload: AuthorizationPayload & ComicEpisodesPayload): Promise<ComicEpisodesResponse>

.fetchComicEpisodePages

/**
 * Fetch pages of the specified comic episode using the given payload.
 *
 * @param payload - AuthorizationPayload & ComicEpisodePagesPayload {
 *   token   - Access token
 *   comicId - Specify comic id
 *   order   - Specify episode order of the comic
 *   page    - Page number (optional)
 * }
 * @return ComicEpisodePagesResponse
 */
PicaComicAPI.fetchComicEpisodePages(payload: AuthorizationPayload & ComicEpisodePagesPayload): Promise<ComicEpisodePagesResponse>

.fetchComicComments

/**
 * Fetch comic comments using the given payload.
 *
 * @param payload - AuthorizationPayload & ComicCommentsPayload {
 *   token   - Access token
 *   comicId - Specify comic id
 *   page    - Page number (optional)
 * }
 * @return ComicCommentsResponse
 */
PicaComicAPI.fetchComicComments(payload: AuthorizationPayload & ComicCommentsPayload): Promise<ComicComments>

.searchComics

/**
 * Search comics using the given payload.
 *
 * @param payload - AuthorizationPayload & SearchComicsPayload {
 *   token      - Access token
 *   keyword    - Keyword
 *   categories - Specify category name array (e.g.: ['Cosplay']) (optional)
 *   page       - Page number (optional)
 *   sort       - Sorting type (optional)
 * }
 * @return SearchComicsResponse
 */
PicaComicAPI.searchComics(payload: AuthorizationPayload & SearchComicsPayload): Promise<Comics>

.switchComicLike

/**
 * Switch the comic as like or unlike using the given payload.
 *
 * @param payload - AuthorizationPayload & ComicIdPayload {
 *   toke    - Access token
 *   comicId - Specify comic id
 * }
 * @return SwitchComicLikeResponse
 */
PicaComicAPI.switchComicLike(payload: AuthorizationPayload & ComicIdPayload): Promise<SwitchComicLikeResponse>

.switchComicFavourite

/**
 * Switch the comic as favourite or un_favourite using the given payload.
 *
 * @param payload - AuthorizationPayload & ComicIdPayload {
 *   toke    - Access token
 *   comicId - Specify comic id
 * }
 * @return SwitchComicFavouriteResponse
 */
PicaComicAPI.switchComicFavourite(payload: AuthorizationPayload & ComicIdPayload): Promise<SwitchComicFavouriteResponse>

.setUserProfileSlogan

/**
 * Set the slogan of the user profile with the given payload.
 *
 * @param payload - AuthorizationPayload & UserProfileSloganPayload {
 *   toke   - Access token
 *   slogan - Slogan (Cannot be blank)
 * }
 * @return BaseResponse<undefined>
 */
PicaComicAPI.setUserProfileSlogan(payload: AuthorizationPayload & UserProfileSloganPayload): Promise<BaseResponse<undefined>>

.stringifyImageUrl

/**
 * Stringify the given image media data into image url.
 *
 * @param payload - ImageMediaPayload = ImageMedia | {
 *   path       - Path name
 *   fileServer - File server (Optional)
 * }
 * @return string
 */
PicaComicAPI.stringifyImageUrl(payload: ImageMediaPayload): string

.createImageRequest

/**
 * Create an image request from the given image media data.
 *
 * @param payload - ImageMediaPayload = ImageMedia | {
 *   path       - Path name
 *   fileServer - File server (Optional)
 * }
 * @return Request (Got request)
 */
PicaComicAPI.createImageRequest(payload: ImageMediaPayload): got.Request

.createImageRequestAsBuffer

/**
 * Create an image request and as buffer from the given image media data.
 *
 * @param payload - ImageMediaPayload = ImageMedia | {
 *   path       - Path name
 *   fileServer - File server (Optional)
 * }
 * @return Buffer
 */
PicaComicAPI.createImageRequestAsBuffer(payload: ImageMediaPayload): Promise<Buffer>

Client

The client is just a wrapper for a single account operation, and does not need to handle the problem of token invalidation by itself.

Note: The client is similar to the API, but does not provide register and signIn methods. The payload parameters of other methods do not need to provide the token access token property.

import { PicaComicClient } from '@l2studio/picacomic-api'

export class PicaComicClient {
  public readonly email: string
  public readonly password: string
  public readonly api: PicaComicAPI
  public readonly onTokenIssued?: (token: string) => void | Promise<void>
  public token: string
  constructor (options: PicaComicClientOptions)
}

Client Options

interface PicaComicClientOptions extends Omit<PicaComicAPIOptions, 'reauthorizationTokenCallback'> {
  /// Extende PicaComicAPIOptions options
  /// See above
  fetch?: Got | ExtendOptions
  appOptions?: Partial<PicaComicOptions>
  ///

  // Owned options
  email: string         // PicaComic account email
  password: string      // PicaComic account password
  token?: string        // PicaComic account access token (Optional)

  // Callback function for re-authenticate and consuming a new token when the token is invalid. (Optional)
  // Example:
  //   onTokenIssued (token) {
  //     console.log('New token:', token)
  //     fs.writeFileSync('token.txt', token)
  //   }
  onTokenIssued?: (token: string) => void | Promise<void>
}

Example

When the token expires, it will re-login and renew the token and persistence. No need to provide token every time.

import { PicaComicClient } from '@l2studio/picacomic-api'
import path from 'path'
import fs from 'fs'

const tokenFile = path.join(__dirname, '.token') // Persistent token
const picacomic = new PicaComicClient({
  email   : 'your picacomic email',
  password: 'your picacomic password',
  token: fs.existsSync(tokenFile) ? fs.readFileSync(tokenFile, 'utf8') : undefined,
  onTokenIssued (token) {
    console.log('New token:', token)
    fs.writeFileSync(tokenFile, token) // Update persistent token
  }
})

;(async () => {
  const response = await picacomic.fetchComics({ category: 'Cosplay' })
  console.log(response)
})()

FAQ

How to configure http proxy

See also Got agent.

Please configure the fetch property of PicaComicAPIOptions or PicaComicClientOptions.

Example using tunnel:

import { PicaComicClient } from '@l2studio/picacomic-api'
import tunnel from 'tunnel'

const picacomic = new PicaComicClient({
  fetch: {
    agent: {
      https: tunnel.httpsOverHttp({
        // Your http proxy server host and port
        proxy: {
          host: '127.0.0.1',
          port: 10809
        }
      }) as any
    }
  },
  ...other
})

License

Apache-2.0