diff options
| author | Fuwn <[email protected]> | 2021-04-26 15:42:39 -0700 |
|---|---|---|
| committer | Fuwn <[email protected]> | 2021-04-26 15:42:39 -0700 |
| commit | 1b82b0a7776aee31f553fb588be4fa9691592248 (patch) | |
| tree | d0a678e4a6735dfd92e92b1aab33a3447c3666ee /src | |
| parent | fmt: Change case (diff) | |
| download | api-1b82b0a7776aee31f553fb588be4fa9691592248.tar.xz api-1b82b0a7776aee31f553fb588be4fa9691592248.zip | |
major: :star:
Diffstat (limited to 'src')
| -rw-r--r-- | src/constants.rs | 8 | ||||
| -rw-r--r-- | src/main.rs | 27 | ||||
| -rw-r--r-- | src/routes.rs | 78 | ||||
| -rw-r--r-- | src/structures.rs | 28 | ||||
| -rw-r--r-- | src/utils.rs | 52 |
5 files changed, 193 insertions, 0 deletions
diff --git a/src/constants.rs b/src/constants.rs new file mode 100644 index 0000000..adbde90 --- /dev/null +++ b/src/constants.rs @@ -0,0 +1,8 @@ +// Copyleft 2021-2021 The Senpy Club +// SPDX-License-Identifier: GPL-3.0-only + +pub const GITHUB_USER_CONTENT: &str = + "https://raw.githubusercontent.com/laynH/Anime-Girls-Holding-Programming-Books/master/"; +pub const GITHUB_API_ENDPOINT: &str = "https://api.github.com/repos/laynH/Anime-Girls-Holding-Progr\ +amming-Books/git/trees/master?recursive=1"; +pub const USER_AGENT: &str = env!("CARGO_PKG_NAME"); diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..35af208 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,27 @@ +// Copyleft 2021-2021 The Senpy Club +// SPDX-License-Identifier: GPL-3.0-only + +#![feature(proc_macro_hygiene, decl_macro, type_ascription)] + +#[macro_use] +extern crate rocket; + +pub mod constants; +pub mod routes; +pub mod structures; +pub mod utils; + +#[launch] +fn rocket() -> _ { + dotenv::dotenv().ok(); + + rocket::build().mount("/", routes![routes::index]).mount( + "/api/v1", + routes![ + routes::github, + routes::languages, + routes::language, + routes::random + ], + ) +} diff --git a/src/routes.rs b/src/routes.rs new file mode 100644 index 0000000..e492404 --- /dev/null +++ b/src/routes.rs @@ -0,0 +1,78 @@ +// Copyleft 2021-2021 The Senpy Club +// SPDX-License-Identifier: GPL-3.0-only + +use rand::{thread_rng, Rng}; +use rocket_contrib::json::Json; + +use crate::{ + structures::{GitHubAPIResponse, SenpyRandom}, + utils::{filter_images_by_language, filter_languages, github_api}, +}; + +#[get("/")] +pub fn index() -> &'static str { + r#"# senpy-api +## routes +if a language requires a parameter, it will be notated like <this>. +for example; if a route is notated as "/api/v1/route?<parameter>", you can +access that route via the url +"http://this.domain/api/v1/route?parameter=something" + +- / + - /: index page (you are here) + +- /api/v1 + - /github: github api mirror + - /languages: a list of all languages that appear in _the_ repository + - /language?<lang>: get a list of all images that pertain to the language "<lang>" + +## notes +### rate-limit (s) +there aren't any rate-limits or whatnot on api usage but don't abuse it, it only takes one bad +apple to spoil the lot. + +### contributing +if you'd like to support the project in anyway, check out the repository! +https://github.com/senpy-club/api + +### supporting +if you would like to support my development ventures, visit my github profile here :3 +https://github.com/fuwn + +### license +gnu general public license v3.0 (gpl-3.0-only) +https://github.com/senpy-club/api/blob/main/LICENSE"# +} + +#[get("/github")] +pub async fn github() -> Json<GitHubAPIResponse> { Json(github_api().await.unwrap()) } + +#[get("/languages")] +pub async fn languages() -> Json<Vec<String>> { Json(filter_languages().await) } + +#[get("/language?<lang>")] +pub async fn language(lang: Option<String>) -> Json<Vec<String>> { + // lang.map(async |lang| Json(filter_images_by_language(lang).await)) + // .unwrap_or_else(|| Json(vec!["invalid language or no language + // specified".to_string()])); + + return if lang.is_none() { + Json(vec!["invalid language or no language specified".to_string()]) + } else { + Json(filter_images_by_language(lang.unwrap()).await) + }; +} + +#[get("/random")] +pub async fn random() -> Json<SenpyRandom> { + let filtered_languages = filter_languages().await; + let random_language = + &filtered_languages[thread_rng().gen_range(0..filtered_languages.len() - 1)]; + let filtered_images = filter_images_by_language(random_language.clone().to_owned()).await; + let random_image = &filtered_images[thread_rng().gen_range(0..filtered_images.len() - 1)]; + + Json(SenpyRandom { + language: random_language.clone().to_owned(), + image: random_image.clone().to_owned(), + }) +} diff --git a/src/structures.rs b/src/structures.rs new file mode 100644 index 0000000..2a85111 --- /dev/null +++ b/src/structures.rs @@ -0,0 +1,28 @@ +// Copyleft 2021-2021 The Senpy Club +// SPDX-License-Identifier: GPL-3.0-only + +use serde_derive::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug)] +pub struct GitHubAPIResponse { + pub sha: String, + pub url: String, + pub tree: Vec<GitHubAPIResponseTree>, + pub truncated: bool, +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct GitHubAPIResponseTree { + pub path: String, + pub mode: String, + #[serde(rename = "type")] + pub _type: String, + pub sha: String, + pub url: String, +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct SenpyRandom { + pub(crate) language: String, + pub image: String, +} diff --git a/src/utils.rs b/src/utils.rs new file mode 100644 index 0000000..d51a813 --- /dev/null +++ b/src/utils.rs @@ -0,0 +1,52 @@ +// Copyleft 2021-2021 The Senpy Club +// SPDX-License-Identifier: GPL-3.0-only + +use crate::{ + constants::{GITHUB_API_ENDPOINT, GITHUB_USER_CONTENT, USER_AGENT}, + structures::GitHubAPIResponse, +}; + +pub async fn github_api() -> Result<GitHubAPIResponse, reqwest::Error> { + Ok( + reqwest::Client::new() + .get(GITHUB_API_ENDPOINT) + .header("User-Agent", USER_AGENT) + .header( + "Authorization", + format!("token {}", std::env::var("GITHUB_TOKEN").unwrap()), + ) + .send() + .await? + .json::<GitHubAPIResponse>() + .await?, + ) +} + +pub async fn filter_languages() -> Vec<String> { + let mut languages = vec![]; + + for i in github_api().await.unwrap().tree { + if i._type == "tree" { + languages.push(i.path); + } + } + + languages +} + +pub async fn filter_images_by_language(language: String) -> Vec<String> { + let mut images = vec![]; + + for i in github_api().await.unwrap().tree { + // Example: + // "Language/Image.png" would become ["Language", "Image.png"] + + // TODO: Fix this with type_ascription + let x: Vec<&str> = i.path.split("/").collect(); + if x[0] == language && i.path.contains('/') { + images.push(format!("{}{}", GITHUB_USER_CONTENT, i.path)) + } + } + + images +} |