Skip to content

Eltik/Cronchy

Repository files navigation

Cronchy

Crunchyroll wrapper using webscraping utilities. Made using Crunchyroll's beta API. Created by Eltik, Inumaki, and the Consumet Community.

Installation

Cronchy is available on NPM via the following command:

$ npm install cronchy

However, you can also clone the GitHub via git clone https://github.com/Eltik/Cronchy. If you are cloning the repository, you can build the project using the following commands:

$ npm run install
$ npm run build

It is also important to note that Cronchy requires TypeScript and NodeJS to run, so if you have difficulties installing the library make sure to check that your machine supports both.

Basic Documentation

Constructor

Cronchy requires a premium account to work properly (and no, we will/cannot support non-premium accounts). To initialize a Cronchy "instance", pass your email and password into the constructor.

// ES6
import Cronchy from "cronchy";
// commonjs
const Cronchy = require("cronchy").default;

const instance = new Cronchy("[email protected]", "password123");

There is a third argument you can pass into the constructor which is the token. As of now, Crunchyroll requires a token header for all requests that is constant. The token should work for all accounts, but in the case it doesn't, you can provide a it into the constructor in the case Crunchyroll changes how their API works. Support will not be provided on how to fetch the token, but for peace of mind the argument is there just in case.

...
const instance = new Cronchy("[email protected]", "password123", "a3ZvcGlzdXZ6Yy0teG96Y21kMXk6R21JSTExenVPVnRnTjdlSWZrSlpibzVuLTRHTlZ0cU8=");

Logging In

To use all functions of the package, you need to run the login() function beforehand. This is important because Crunchyroll requires an access_token header for each request. Some other functions such as the querySeason() function require other account data such as the signature and policy of the account. Don't worry, though; this function is completely safe and simulates a real login.

const instance = ...;
await instance.login(); // Returns Promise<AccountData>

interface AccountData {
    access_token: string;
    refresh_token?: string;
    expires_in: number;
    token_type: string;
    scope: string;
    country: string;
    account_id: string;
    signature: string;
    key_pair_id: string;
    bucket: string;
    policy: string;
}

For convenience sake, the login() function will store all account data in the instance object. This means that if you are running a web server, upon the server's startup you can run the login() function to prevent having to continuously fetch the access_token. For example:

import Fastify from "fastify";
import Cronchy from "cronchy";

const instance = new Cronchy(...);

const fastify = Fastify({
    ...
});

fastify.listen({ port: 3000 }, (err, address) => {
    if (err) throw err;
    
    instance.login().then((accountData) => {
        console.log(`Listening to ${address}.`);
    });
})

Searching

Searching using the Cronchy package is simple. Just run instance.search(query, amount?); to search through all of Crunchyroll for a specific show. amount is an optional parameter that by default will input 8 if not specified.

const instance = new Cronchy(...);
/**
 * @param query Search query. Takes a string.
 * @param amount Max amount of search results. Takes a number.
 * returns Promise<SearchData>
 */
instance.search("Bocchi the Rock", 5);

interface SearchData {
    total: number;
    data: Array<SearchResult>;
    meta: JSON;
}

interface SearchResult {
    type: MediaType["top_results"] | MediaType["series"] | MediaType["movie_listing"] | MediaType["episode"];
    count: number;
    items: Array<SearchQuery>;
}

Getting Episodes

Fetchin episodes requires the ID of the show. In past versions of Cronchy you were required to input a SearchQuery object. However, I realized that Crunchyroll actually fetches the show info based on the show ID so I removed that parameter. getEpisodes() also requires the locale of the show, but most of the time it's just en-US. If you need to confirm the locale of the show you are querying, you can run the getLocaleFromSearchQuery() function and input a SearchQuery object. Lastly, the mediaType parameter is the type of the show as the name suggests. You can run the getMediaTypeFromSearchQuery() function and input a SearchQuery object to fetch it. If either the locale or media type return undefined, it most likely means that the show has not been released officially on Crunchyroll (eg. it's not available yet).

const instance = new Cronchy(...);
/**
 * @param id SearchQuery id. Can be obtained from the search function.
 * @param locale The locale of the show. Can be obtained from the search function or via getLocaleFromSearchQuery().
 * @param mediaType The type of media. Must be a valid Crunchyroll series string.
 * @param fetchAll Whether or not to fetch all "seasons" (whatever Crunchyroll means by that lol). If false, only the the episodes from the "season" will be fetched.
*/
const results = await instance.search(...);
const locale = instance.getLocaleFromSearchQuery(result.data[0].items[0]);
const mediaType = instance.getMediaTypeFromSearchQuery(result.data[0].items[0]);
await instance.getEpisodes(results.data[0].items[0].id, locale, mediaType, false);

interface Show {
    id: string;
    title: string;
    isAdult: string|boolean;
    image: string;
    cover: string;
    description: string;
    releaseDate: number;
    genres: string[];
    season: string;
    hasDub: boolean;
    hasSub: boolean;
    rating: string;
    recommendations: any; // This needs to be fixed, but it returns data correctly.
    episodes: any; // This to. TypeScript moment :pray:
}

To elaborate on the fetchAll parameter, fetching all episodes will take longer but also get all the episodes Crunchyroll has. Crunchyroll has "seasons", or multiple "series" of episodes. As a result, the fetchAll option is thus required for fetching all episodes as the name suggests.

Getting Sources

Crunchyroll stores the source of their videos as m3u8s, or streamable files. By default, this package is meant to be lightweight and doesn't contain a convertor. But considering that m3u8s are better for streaming videos rather than mp4s, it makes sense that the getSources() function will return an m3u8 instead.

const instance = new Cronchy(...);
/**
 * @param episodeId The episode ID of the show.
 * @param locale The locale of the episode. For example, "en-US".
 * returns Promise<Sources>
*/
await instance.getSources("G6Q4Q3V1R", "en-US");

interface Sources {
    sources: Array<Source>;
    subtitles: Array<Subtitle>;
}

interface Source {
    url: string;
    quality: string;
    isM3U8: boolean;
}

interface Subtitle {
    url: string;
    lang: string;
    format: string;
}

Contribution to this documentation would be appreciated as it is not finished.

TODO

  • MalSync
  • Cleanup (the whole thing is sort of messy) If anyone wishes to contribute, that would be appreciated. Feel free to create a Pull Request.

Rip Kamyroll

About

Crunchyroll Wrapper.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published