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
#![doc(alias = "webhooks")]
//! Various topics for webhooks

use crate::helix::{self, Request, RequestGet, Response};
use helix::ser;
use serde::{de::DeserializeOwned, Serialize};

pub mod hypetrain;
pub mod moderation;
pub mod streams;
pub mod subscriptions;
pub mod users;

// FIXME: Missing Topic: Extension Transaction Created

/// A webhook topic.
pub trait Topic: DeserializeOwned + Serialize + PartialEq {
    /// Helix response
    type Helix: RequestGet + Request;

    /// URL of topic sans `https://api.twitch.tv/helix/`
    const PATH: &'static str;

    /// Scopes needed by this endpoint
    #[cfg(feature = "twitch_oauth2")]
    const SCOPE: &'static [twitch_oauth2::Scope];
    /// Optional scopes needed by this endpoint
    #[cfg(feature = "twitch_oauth2")]
    const OPT_SCOPE: &'static [twitch_oauth2::Scope] = &[];

    /// Defines layout of the url parameters.
    fn query(&self) -> Result<String, ser::Error> { ser::to_string(&self) }

    /// Returns full URI for the request, including query parameters.
    fn get_uri(&self) -> Result<http::Uri, helix::InvalidUri> {
        use std::str::FromStr;
        http::Uri::from_str(&format!(
            "{}{}?{}",
            crate::TWITCH_HELIX_URL,
            <Self as Topic>::PATH,
            self.query()?
        ))
        .map_err(Into::into)
    }
    /// Returns bare URI for the request, NOT including query parameters.
    fn get_bare_uri() -> Result<http::Uri, helix::InvalidUri> {
        use std::str::FromStr;
        http::Uri::from_str(&format!(
            "{}{}?",
            crate::TWITCH_HELIX_URL,
            <Self as Topic>::PATH,
        ))
        .map_err(Into::into)
    }

    /// Parse payload received on webhook.
    ///
    /// Forwards to [`RequestGet::parse_response`]
    fn parse_payload(
        response: http::Response<Vec<u8>>,
    ) -> Result<
        Response<Self::Helix, <Self::Helix as Request>::Response>,
        crate::helix::HelixRequestGetError,
    >
    where Self: Sized {
        <Self::Helix>::parse_response(None, &Self::get_bare_uri()?, response)
    }
}