crunchyroll_rs/lib.rs
1//! # crunchyroll-rs
2//!
3//! An easy-to-use, batteries-included library for the undocumented
4//! [Crunchyroll](https://www.crunchyroll.com/) api, completely written in Rust.
5//!
6//! You can use a premium account as well as a non-premium account to use this library, but you
7//! will be limited to your account tier access privileges (=> you can't access a premium-only
8//! series with a free account).
9//!
10//! The library has some features to ensure a flawless experience in a ⚡🦀 blazingly fast
11//! environment.
12//! - Full [Tokio](https://tokio.rs/) compatibility.
13//! - Solid tests to [ensure api compatability](#implementation).
14//!
15//! # Getting started
16//!
17//! Before you can do anything, you have to instantiate a new [`Crunchyroll`] struct at first. This
18//! internally creates a new [`crunchyroll::CrunchyrollBuilder`] instance. All functions of this
19//! struct are chaining, which means you can build a working Crunchyroll instance in one expression.
20//!
21//! ```
22//! use crunchyroll_rs::{Crunchyroll, Locale};
23//!
24//! let crunchy = Crunchyroll::builder()
25//! // set the language in which results should be returned
26//! .locale(Locale::en_US)
27//! // login with user credentials (other login options are also available)
28//! // support for username login was dropped by Crunchyroll on December 6th, 2023
29//! .login_with_credentials("email", "password", Default::default())
30//! .await?;
31//! ```
32//!
33//! ## Request media
34//!
35//! You can request media like series, episodes, movies, ... with their corresponding function in
36//! the [`Crunchyroll`] struct. Use `Crunchyroll::*_from_id` to get them while `*` is the media type.
37//!
38//! ```
39//! // get the series with the id 'GY8VEQ95Y'
40//! let series: Series = crunchy.media_from_id("GY8VEQ95Y").await?;
41//!
42//! // get the episode with the id 'GRDKJZ81Y'
43//! let episode: Episode = crunchy.media_from_id("GY8VEQ95Y").await?;
44//!
45//! ```
46//!
47//! If you want to get the children of a "container" media like a series or season, these types
48//! implements the appropriate functions to archive this.
49//!
50//! ```
51//! let seasons = series
52//! // get the seasons of this series
53//! .seasons()
54//! .await?;
55//! ```
56//!
57//! ## Streaming
58//!
59//! _All streams are DRM protected. The library does not contain logic to decrypt it, so if you want
60//! to do this, you have to implement it yourself._
61//!
62//! This crate allows you to get the actual video streams behind episodes and movies.
63//!
64//! ```
65//! let stream = episode
66//! .stream()
67//! .await?;
68//! ```
69//!
70//! Crunchyroll uses the [DASH] video streaming format to distribute their streams. The logic to
71//! work with these formats is already implemented into this crate.
72//!
73//! ```
74//! let mut stream_data = stream
75//! .stream_data(None)
76//! .await?
77//! .unwrap();
78//!
79//! // sort the streams to get the stream with the best resolution / bitrate at first
80//! stream_data.video.sort_by(|a, b| a.bandwidth.cmp(&b.bandwidth).reverse());
81//! stream_data.audio.sort_by(|a, b| a.bandwidth.cmp(&b.bandwidth).reverse());
82//!
83//! let sink = &mut std::io::sink();
84//!
85//! // get the segments / video chunks of the first stream (which is the best after it got sorted
86//! // above)
87//! let video_segments = stream_data.video[0].segments();
88//! let audio_segments = stream_data.audio[0].segments();
89//! // iterate through every segment and write it to the provided writer (which is a sink in this
90//! // case; it drops its input immediately). writer can be anything which implements `std::io::Write`
91//! // like a file, a pipe, ...
92//! for video_segment in video_segments {
93//! sink.write_all(&video_segment.data().await?)?;
94//! }
95//! for audio_segment in audio_segments {
96//! sink.write_all(&audio_segment.data().await?)?;
97//! }
98//! ```
99//!
100//! # Bugs
101//! Crunchyroll is awful in keep their api clean. Thus, some things are broken, will break for no
102//! reason or aren't well implemented (if at all). The methods added with the
103//! `experimental-stabilizations` feature (`CrunchyrollBuilder::stabilization_*`) can be used to
104//! prevent some issues. Note that there is no guarantee that these functions will work or that they
105//! will not break anything.
106//!
107//! ### Cloudflare
108//! Crunchyroll uses the cloudflare bot protection to detect if requests are made by a human.
109//! Obviously this crate makes automated requests and thus, Cloudflare sometimes blocks requests.
110//! The crate catches these errors with the [`error::Error::Block`] enum field. The block
111//! occurs depending on different factors like your location. If such a block occurs you can try to
112//! create a custom [`reqwest::Client`] which has the needed configuration to bypass this check,
113//! like other user agents or tls backends (note that [`reqwest`] currently only supports
114//! [`native-tls`](https://docs.rs/native-tls/latest/native_tls/) besides [`rustls`] as tls backend,
115//! which is confirmed to work with openssl on Linux only, on Windows the blocks are even more
116//! aggressive). The configurations may vary on the factors addressed so there is no 100% right way
117//! to do it.
118//!
119//! # Features
120//!
121//! - **parse** *(enabled by default)*: Enables url parsing.
122//! - **tower**: Enables the usage of a [tower](https://docs.rs/tower) compatible middleware.
123//! - **experimental-stabilizations**: Provides some functions to maybe fix broken api results. See
124//! [Bugs](#bugs) for more information.
125//!
126//! # Implementation
127//! To ensure at least all existing parts of the library are working as expected, a special feature
128//! only for testing is implemented. When running tests with the `__test_strict` feature, it ensures
129//! that no fields were added or removed from an api response, otherwise the associated test will
130//! fail.
131//!
132//! [DASH]: https://en.wikipedia.org/wiki/Dynamic_Adaptive_Streaming_over_HTTP
133
134#![cfg_attr(docsrs, feature(doc_cfg))]
135
136pub mod account;
137pub mod categories;
138pub mod common;
139pub mod crunchyroll;
140pub mod devices;
141pub mod error;
142pub mod feed;
143pub mod list;
144pub mod media;
145#[cfg(feature = "parse")]
146#[cfg_attr(docsrs, doc(cfg(feature = "parse")))]
147pub mod parse;
148pub mod payment;
149pub mod profile;
150pub mod search;
151
152// internal
153mod internal;
154
155// internal
156pub(crate) use common::Request;
157pub(crate) use crunchyroll::Executor;
158pub(crate) use error::Result;
159pub(crate) use internal::macros::{enum_values, options};
160pub(crate) use internal::serde::EmptyJsonProxy;
161
162pub use crunchyroll::{Crunchyroll, Locale};
163pub use error::Error;
164pub use media::{
165 Artist, Concert, Episode, MediaCollection, Movie, MovieListing, MusicVideo, Season, Series,
166};
167#[cfg(feature = "parse")]
168pub use parse::{UrlType, parse_url};
169
170#[cfg(feature = "__test_strict")]
171use internal::strict::StrictValue;