mod commit;
mod common;
mod issue;
mod middleware;
mod org;
mod release;
mod repo;
mod user;
use crate::{
commit::GitCodeCommit,
common::JsonValue,
issue::GitCodeIssue,
middleware::{HeaderMiddleware, ResponseMiddleware},
org::GitCodeOrg,
release::GitCodeRelease,
repo::GitCodeRepo,
user::GitCodeUser,
};
pub use nipaw_core::{Client, Commit, Config, Error, Issue, Org, Provider, Release, Repo, Result, Token, User};
use reqwest_middleware::{ClientBuilder, ClientWithMiddleware};
use std::sync::Arc;
use tokio::sync::RwLock;
#[derive(Debug, Clone)]
pub(crate) struct GitCodeConfig {
pub(crate) token: Option<String>,
pub(crate) base_url: String,
pub(crate) api_url: String,
pub(crate) web_api_url: String,
}
#[derive(Debug, Clone)]
pub(crate) struct GitCodeClientInner {
pub(crate) config: GitCodeConfig,
pub(crate) client: Arc<RwLock<Arc<ClientWithMiddleware>>>,
}
impl Default for GitCodeConfig {
fn default() -> Self {
Self {
token: None,
base_url: "https://gitcode.com".to_string(),
api_url: "https://api.gitcode.com/api/v5".to_string(),
web_api_url: "https://web-api.gitcode.com".to_string(),
}
}
}
impl GitCodeConfig {
pub fn set_token(&mut self, token: &str) {
self.token = Some(token.to_string());
}
}
#[derive(Debug, Clone)]
pub struct GitCodeClient {
pub(crate) inner: Arc<GitCodeClientInner>,
}
impl Default for GitCodeClient {
fn default() -> Self {
let client = reqwest::Client::new();
Self {
inner: Arc::new(GitCodeClientInner {
config: GitCodeConfig::default(),
client: Arc::new(RwLock::new(Arc::new(
ClientBuilder::new(client)
.with(HeaderMiddleware)
.with(ResponseMiddleware)
.build(),
))),
}),
}
}
}
impl GitCodeClient {
pub fn new() -> Self {
Self::default()
}
}
impl Token for GitCodeClient {
fn set_token(&mut self, token: &str) -> Result<()> {
if token.is_empty() {
return Err(Error::TokenEmpty);
}
Arc::make_mut(&mut self.inner).config.set_token(token);
Ok(())
}
}
impl nipaw_core::Proxy for GitCodeClient {
fn set_proxy(&mut self, proxy: &str) -> Result<()> {
let client = reqwest::Client::builder().proxy(reqwest::Proxy::all(proxy)?).build()?;
*self.inner.client.try_write().unwrap() = Arc::new(
ClientBuilder::new(client).with(HeaderMiddleware).with(ResponseMiddleware).build(),
);
Ok(())
}
}
impl Provider for GitCodeClient {
type User = GitCodeUser;
type Org = GitCodeOrg;
type Repo = GitCodeRepo;
type Commit = GitCodeCommit;
type Issue = GitCodeIssue;
type Release = GitCodeRelease;
fn user(&self) -> GitCodeUser {
GitCodeUser(self.inner.clone())
}
fn org(&self) -> GitCodeOrg {
GitCodeOrg(self.inner.clone())
}
fn repo(&self) -> GitCodeRepo {
GitCodeRepo(self.inner.clone())
}
fn commit(&self) -> GitCodeCommit {
GitCodeCommit(self.inner.clone())
}
fn issue(&self) -> GitCodeIssue {
GitCodeIssue(self.inner.clone())
}
fn release(&self) -> GitCodeRelease {
GitCodeRelease(self.inner.clone())
}
}
pub(crate) async fn get_user_repo_count(
client: Arc<ClientWithMiddleware>,
config: &GitCodeConfig,
user_name: &str,
) -> Result<u64> {
let (base_url, web_api_url) = (&config.base_url, &config.web_api_url);
let url = format!(
"{}/uc/api/v1/events/{}/contributions?username={}",
web_api_url, user_name, user_name
);
let request = client.get(url).header("Referer", base_url);
let resp = request.send().await?;
let repo_info: JsonValue = resp.json().await?;
let repo_count = repo_info.0.get("total").and_then(|total| total.as_u64()).unwrap_or(0);
Ok(repo_count)
}