From 72a6ce956406b68a68d23e280c24b1d4fcc1a0a7 Mon Sep 17 00:00:00 2001 From: realaravinth Date: Tue, 17 May 2022 01:03:54 +0530 Subject: [PATCH] feat: define core forge interface to implement starchart --- forge/forge-core/Cargo.toml | 18 +++++ forge/forge-core/src/lib.rs | 139 ++++++++++++++++++++++++++++++++++++ 2 files changed, 157 insertions(+) create mode 100644 forge/forge-core/Cargo.toml create mode 100644 forge/forge-core/src/lib.rs diff --git a/forge/forge-core/Cargo.toml b/forge/forge-core/Cargo.toml new file mode 100644 index 0000000..ff0739b --- /dev/null +++ b/forge/forge-core/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "forge-core" +repository = "https://github.com/forgeflux-org/starchart" +version = "0.1.0" +authors = ["realaravinth "] +description = "ForgeFlux StarChart - Federated forge spider" +documentation = "https://forgeflux.org/" +edition = "2021" +license = "AGPLv3 or later version" + + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +async-trait = "0.1.51" + +[dependencies.db-core] +path = "../../db/db-core" diff --git a/forge/forge-core/src/lib.rs b/forge/forge-core/src/lib.rs new file mode 100644 index 0000000..894d7e4 --- /dev/null +++ b/forge/forge-core/src/lib.rs @@ -0,0 +1,139 @@ +/* + * ForgeFlux StarChart - A federated software forge spider + * Copyright © 2022 Aravinth Manivannan + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +use std::collections::{HashMap, HashSet}; +use std::sync::Arc; + +use async_trait::async_trait; +use db_core::prelude::*; + +pub mod prelude { + pub use super::*; + pub use async_trait::async_trait; +} + +pub mod dev { + pub use super::*; + pub use async_trait::async_trait; + pub use db_core; +} + +#[derive(Clone, Debug)] +pub struct User<'a> { + /// hostname of the forge instance: with scheme but remove trailing slash + /// hostname can be derived from html_link also, but used to link to user's forge instance + pub hostname: &'a str, + /// username of the user + pub username: Arc, + /// html link to the user profile + pub html_link: String, + /// OPTIONAL: html link to the user's profile photo + pub profile_photo: Option, +} + +impl<'a> From<&'a User<'a>> for AddUser<'a> { + fn from(u: &'a User) -> Self { + Self { + hostname: u.hostname, + username: u.username.as_str(), + html_link: &u.html_link, + profile_photo: u.profile_photo.as_deref(), + } + } +} + +#[derive(Clone, Debug)] +/// add new repository to database +pub struct Repository<'a> { + /// html link to the repository + pub html_link: String, + /// repository topic tags + pub tags: Option>>, + /// hostname of the forge instance: with scheme but remove trailing slash + /// hostname can be deras_ref().map(|p| p.as_str()),ived from html_link also, but used to link to user's forge instance + pub hostname: &'a str, + /// repository name + pub name: String, + /// repository owner + pub owner: Arc>, + /// repository description, if any + pub description: Option, + /// repository website, if any + pub website: Option, +} + +impl<'a> From<&'a Repository<'a>> for AddRepository<'a> { + fn from(r: &'a Repository) -> Self { + let tags = if let Some(rtags) = &r.tags { + let mut tags = Vec::with_capacity(rtags.len()); + for t in rtags.iter() { + tags.push(t.as_str()); + } + Some(tags) + } else { + None + }; + Self { + hostname: r.hostname, + name: &r.name, + description: r.description.as_deref(), + owner: r.owner.username.as_str(), + tags, + html_link: &r.html_link, + website: r.website.as_deref(), + } + } +} + +pub type UserMap<'a> = HashMap, Arc>>; +pub type Tags = HashSet>; +pub type Repositories<'a> = Vec>; + +pub struct CrawlResp<'a> { + pub repos: Repositories<'a>, + pub tags: Tags, + pub users: UserMap<'a>, +} + +#[async_trait] +pub trait SCForge: std::marker::Send + std::marker::Sync + CloneSPForge { + async fn is_forge(&self) -> bool; + async fn crawl(&self, limit: u64, page: u64) -> CrawlResp; + fn get_hostname(&self) -> &str; + fn forge_type(&self) -> ForgeImplementation; +} + +/// Trait to clone SCForge +pub trait CloneSPForge { + /// clone Forge + fn clone_forge(&self) -> Box; +} + +impl CloneSPForge for T +where + T: SCForge + Clone + 'static, +{ + fn clone_forge(&self) -> Box { + Box::new(self.clone()) + } +} + +impl Clone for Box { + fn clone(&self) -> Self { + (**self).clone_forge() + } +}