takoyaki_core 1.2.0

Core package to build plugins for takoyaki
Documentation
// Import dependencies
use crate::{Cache, PrintableGrid, State, TakoyakiError};
use reqwest::header::{HeaderMap, HeaderName, HeaderValue};
use serde::Serialize;
use std::{collections::HashMap, str::FromStr};

/// The main entry point of the plugin. Takoyaki assembles all the parts of your plugin
/// This function just contains 1 function, that needs to be called at the runtime, and the rest will be handled internally
pub struct Takoyaki;

/// The request type
pub struct Request<'a, T>
where
    T: Serialize,
{
    url: &'a str,
    headers: HashMap<&'a str, &'a str>,
    body: &'a T,
}

/// Defines which keys should be picked for specific value
#[derive(Default, Clone, PartialEq, Debug, Eq)]
pub struct Pick<'a> {
    pub array_root: &'a str,
    pub weeks_root: &'a str,
    pub color_key: &'a str,
    pub contribution_count_key: &'a str,
}

/// Converts a HashMap<&str, &str> to a reqwest::HeaderMap
pub fn convert_to_headermap(headers: HashMap<&str, &str>) -> HeaderMap {
    // Create a new header map
    let mut headermap = HeaderMap::new();

    // Iterate through each of them and push to headermap
    headers.iter().for_each(|(k, v)| {
        headermap.insert(
            HeaderName::from_str(k).unwrap(),
            HeaderValue::from_str(v).unwrap(),
        );
    });

    // Return
    headermap
}

/// Add functions
impl Takoyaki {
    /// Main entry point of the plugin
    ///
    /// ## Arguments:
    ///
    /// * `request` - The request information. This will be used to fetch the data about the contributions
    /// * `pick` - Defines which key should be picked to get the required information
    ///
    /// ## Example:
    ///
    /// ```no_run
    /// use takoyaki_core::Takoyaki;
    ///
    /// Takoyaki::run(
    ///     Request {
    ///         url: "url",
    ///         headers: HashMap::new(),
    ///         body: serde_json::Value::Null
    ///     },
    ///     Pick {
    ///         array_root: "array_root",
    ///         weeks_root: "weeks_root",
    ///         color_key: "color_key",
    ///         contribution_count_key: "contribution_count_key",
    ///     }
    /// )
    /// ```
    ///
    /// For more information, read the docs here - https://takoyaki.kyeboard.me/docs/setting-up-client
    pub async fn run<T>(
        mut request: Request<'_, T>,
        pick: Pick<'_>,
    ) -> Result<(), TakoyakiError>
    where
        T: Serialize,
    {
        // Build a client
        let client = reqwest::Client::new();

        // Add user agent header
        request.headers.insert("User-Agent", "takoyaki");

        // Build a request builder
        let builder = client
            .post(request.url)
            .headers(convert_to_headermap(request.headers))
            .json(request.body);

        // Create a state
        let state = State::new(builder, Cache::new("github"));

        // Resolve the cache
        let data = state.resolve::<serde_json::Value>().await?;

        // Generate the grid
        let mut printable = PrintableGrid::new(pick, data);

        // Pretty print
        printable.pretty_print()?;

        // Ok!
        Ok(())
    }
}

#[cfg(test)]
mod tests {
    use std::collections::HashMap;

    use serde::Serialize;

    use crate::{Pick, Takoyaki};

    #[tokio::test]
    async fn it_works() {
        let mut headers = HashMap::new();

        #[derive(Serialize)]
        pub struct Body {
            query: String,
        }

        let body = Body {
            query: String::from(
                r#"
            query {
            user(login: "kyeboard") {
              name
              contributionsCollection {
                contributionCalendar {
                  colors
                  totalContributions
                  weeks {
                    contributionDays {
                      color
                      contributionCount
                      date
                      weekday
                    }
                    firstDay
                  }
                }
              }
            }
          }
            "#,
            ),
        };

        headers.insert("Authorization", "bearer ");

        Takoyaki::run(
            crate::Request {
                url: "https://api.github.com/graphql",
                headers,
                body: &body,
            },
            Pick {
                array_root: "data.user.contributionsCollection.contributionCalendar.weeks",
                color_key: "color",
                contribution_count_key: "contributionCount",
                weeks_root: "contributionDays",
            },
        )
        .await
        .unwrap();
    }
}