1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
//! Helix responses

/// Helix response
///
/// Every response from Helix may be an error, of type [`ResponseError`],
/// and each successful response, is wrapped within a `data` field, as well
/// as a possible `pagination` field for requests that may search further.
#[derive(PartialEq, Eq, Clone, Debug)]
#[derive(serde::Serialize, serde::Deserialize)]
#[serde(untagged)]
pub enum HelixResponse<T> {
	/// Ok
	Ok(ResponseData<T>),

	/// Error
	Err(ResponseError),
}

impl<T> HelixResponse<T> {
	/// Turns this response into a `Result`
	#[allow(clippy::missing_const_for_fn)] // False positive, we can't use it because `T` might need to be dropped
	pub fn into_result(self) -> Result<ResponseData<T>, ResponseError> {
		match self {
			Self::Ok(ok) => Ok(ok),
			Self::Err(err) => Err(err),
		}
	}
}

/// OAuth response
///
/// Every response from OAuth may be an error, of type [`ResponseError`],
/// bit each successful response, unlike [`HelixResponse`], always contains
/// the response type itself.
#[derive(PartialEq, Eq, Clone, Debug)]
#[derive(serde::Serialize, serde::Deserialize)]
#[serde(untagged)]
pub enum OAuthResponse<T> {
	/// Ok
	Ok(T),

	/// Error
	Err(ResponseError),
}

impl<T> OAuthResponse<T> {
	/// Turns this response into a `Result`
	#[allow(clippy::missing_const_for_fn)] // False positive, we can't use it because `T` might need to be dropped
	pub fn into_result(self) -> Result<T, ResponseError> {
		match self {
			Self::Ok(ok) => Ok(ok),
			Self::Err(err) => Err(err),
		}
	}
}

/// Response data
///
/// The response data for each helix request is wrapped
/// within a `data` field, as well as contain a `pagination`
/// field for requests with multiple pages.
#[derive(PartialEq, Eq, Clone, Debug)]
#[derive(serde::Serialize, serde::Deserialize)]
pub struct ResponseData<T> {
	/// The actual data
	pub data: T,

	/// Possible pagination for the data
	pub pagination: Option<Pagination>,
}

/// Response error
///
/// Every response may return an error. Errors from
/// twitch always contain a status and message, and
/// optionally a further error type.
#[derive(PartialEq, Eq, Clone, Debug)]
#[derive(serde::Serialize, serde::Deserialize)]
#[derive(thiserror::Error)]
#[error("{}: {} ({:?})", status, message, error)]
pub struct ResponseError {
	/// Error
	pub error: Option<String>,

	/// Status
	pub status: usize,

	/// Message
	pub message: String,
}

/// Response pagination
///
/// Represents the current page from the request.
/// May be fed into some requests to get the next page,
/// as a linked-list.
#[derive(PartialEq, Eq, Clone, Debug)]
#[derive(serde::Serialize, serde::Deserialize)]
pub struct Pagination {
	/// Current cursor
	cursor: String,
}