sponsor_block/client/
mod.rs

1//! The SponsorBlock client.
2
3// Modules
4#[cfg(feature = "user")]
5mod user;
6#[cfg(feature = "vip")]
7mod vip;
8
9// Uses
10use core::time::Duration;
11
12use reqwest::{Client as ReqwestClient, ClientBuilder as ReqwestClientBuilder};
13
14// Public Exports
15#[cfg(feature = "user")]
16pub use self::user::*;
17#[cfg(feature = "vip")]
18pub use self::vip::*;
19
20// Type Definitions
21/// A video ID.
22pub type VideoId = String;
23/// The ref version of [`VideoId`] for use in functions.
24pub type VideoIdSlice = str;
25/// A public user ID. This value is a hash of the [`LocalUserId`] and is used
26/// publicly.
27pub type PublicUserId = String;
28/// The ref version of [`PublicUserId`] for use in functions.
29pub type PublicUserIdSlice = str;
30/// A local/private user ID. This value should be kept private and treated like
31/// a password.
32pub type LocalUserId = String;
33/// The ref version of [`LocalUserId`] for use in functions.
34pub type LocalUserIdSlice = str;
35/// A UUID for a segment, uniquely identifying it in the database.
36pub type SegmentUuid = String;
37/// The ref version of [`SegmentUuid`] for use in functions.
38pub type SegmentUuidSlice = str;
39
40/// The client for interfacing with SponsorBlock.
41pub struct Client {
42	// Internal
43	http: ReqwestClient,
44
45	// Config
46	user_id: String,
47	base_url: String,
48	#[cfg(feature = "private_searches")]
49	hash_prefix_length: u8,
50	service: String,
51}
52
53impl Client {
54	/// Creates a new instance of the client with default configuration values.
55	#[must_use]
56	pub fn new<U: Into<LocalUserId>>(user_id: U) -> Self {
57		ClientBuilder::new(user_id).build()
58	}
59
60	/// Creates a new instance of the [`ClientBuilder`].
61	#[must_use]
62	pub fn builder<U: Into<LocalUserId>>(user_id: U) -> ClientBuilder {
63		ClientBuilder::new(user_id)
64	}
65}
66
67/// The builder for the [`Client`].
68pub struct ClientBuilder {
69	// Internal
70	user_agent: String,
71
72	// Config
73	user_id: LocalUserId,
74	base_url: String,
75	#[cfg(feature = "private_searches")]
76	hash_prefix_length: u8,
77	service: String,
78	timeout: Option<Duration>,
79}
80
81impl ClientBuilder {
82	/// The default API URL to use.
83	pub const DEFAULT_BASE_URL: &'static str = "https://sponsor.ajay.app/api";
84	/// The default hash prefix length.
85	#[cfg(feature = "private_searches")]
86	pub const DEFAULT_HASH_PREFIX_LENGTH: u8 = 4;
87	/// The default service value to use.
88	pub const DEFAULT_SERVICE: &'static str = "YouTube";
89	/// The user agent used by the library for requests to the API.
90	pub const DEFAULT_USER_AGENT: &'static str =
91		concat!(env!("CARGO_PKG_NAME"), "-rs/", env!("CARGO_PKG_VERSION"));
92
93	/// Creates a new instance of the struct, with default values for all
94	/// configuration.
95	#[must_use]
96	pub fn new<U: Into<LocalUserId>>(user_id: U) -> Self {
97		Self {
98			user_agent: Self::DEFAULT_USER_AGENT.to_owned(),
99			user_id: user_id.into(),
100			base_url: Self::DEFAULT_BASE_URL.to_owned(),
101			#[cfg(feature = "private_searches")]
102			hash_prefix_length: Self::DEFAULT_HASH_PREFIX_LENGTH,
103			service: Self::DEFAULT_SERVICE.to_owned(),
104			timeout: None,
105		}
106	}
107
108	/// Builds the struct into an instance of [`Client`].
109	#[must_use]
110	pub fn build(&self) -> Client {
111		let mut http = ReqwestClientBuilder::new().user_agent(self.user_agent.clone());
112		if let Some(timeout) = self.timeout {
113			http = http.timeout(timeout);
114		}
115		Client {
116			http: http.build().expect("unable to build the HTTP client"),
117			user_id: self.user_id.clone(),
118			base_url: self.base_url.clone(),
119			#[cfg(feature = "private_searches")]
120			hash_prefix_length: self.hash_prefix_length,
121			service: self.service.clone(),
122		}
123	}
124
125	/// Sets the base URL to access for the API. This includes the `/api` in
126	/// official instances.
127	///
128	/// You should only have to change this if working with a different instance
129	/// of the SponsorBlock database.
130	pub fn base_url(&mut self, base_url: &str) -> &mut Self {
131		self.base_url = base_url.trim_end_matches('/').to_owned();
132		self
133	}
134
135	/// Sets the hash prefix length to use for private searches.
136	///
137	/// This is the number of characters of the hash sent to the server. Smaller
138	/// values will in theory mean more potential matches will have to be sent
139	/// by the API, but will provide more privacy.
140	///
141	/// # Panics
142	/// Panics if not in the range `4 <= hash_prefix_length <= 32`.
143	#[cfg(feature = "private_searches")]
144	pub fn hash_prefix_length(&mut self, hash_prefix_length: u8) -> &mut Self {
145		assert!(hash_prefix_length >= 4);
146		assert!(hash_prefix_length <= 32);
147		self.hash_prefix_length = hash_prefix_length;
148		self
149	}
150
151	/// Sets the service value to use with the API.
152	///
153	/// See <https://wiki.sponsor.ajay.app/w/Types#Service> for more information.
154	pub fn service(&mut self, service: &str) -> &mut Self {
155		self.service = service.to_owned();
156		self
157	}
158
159	/// Sets the HTTP request timeout.
160	///
161	/// The timeout is applied from when the request starts connecting until the
162	/// response body has finished.
163	///
164	/// The default is no timeout.
165	pub fn timeout(&mut self, timeout: Duration) -> &mut Self {
166		self.timeout = Some(timeout);
167		self
168	}
169}