nipaw_github/
lib.rs

1mod commit;
2mod common;
3mod isssue;
4mod middleware;
5mod org;
6mod release;
7mod repo;
8mod user;
9
10use crate::{
11	commit::GitHubCommit,
12	isssue::GitHubIssue,
13	middleware::{HeaderMiddleware, ResponseMiddleware},
14	org::GitHubOrg,
15	release::GitHubRelease,
16	repo::GitHubRepo,
17	user::GitHubUser,
18};
19use async_trait::async_trait;
20pub use nipaw_core::{Client, Commit, Error, Issue, Org, Release, Repo, Result, User};
21use reqwest::Proxy;
22use reqwest_middleware::{ClientBuilder, ClientWithMiddleware};
23use std::sync::Arc;
24use tokio::sync::RwLock;
25
26#[derive(Debug, Clone)]
27pub(crate) struct GitHubConfig {
28	pub(crate) token: Option<String>,
29	pub(crate) api_url: String,
30	pub(crate) base_url: String,
31}
32
33#[derive(Debug, Clone)]
34pub(crate) struct GitHubClientInner {
35	pub(crate) config: GitHubConfig,
36	pub(crate) client: Arc<RwLock<Arc<ClientWithMiddleware>>>,
37}
38
39impl Default for GitHubConfig {
40	fn default() -> Self {
41		Self {
42			token: None,
43			base_url: "https://github.com".to_string(),
44			api_url: "https://api.github.com".to_string(),
45		}
46	}
47}
48
49impl GitHubConfig {
50	/// 设置访问令牌
51	pub fn set_token(&mut self, token: &str) {
52		self.token = Some(token.to_string());
53	}
54	/// 设置 GitHub API 的 URL
55	pub fn set_api_url(&mut self, api_url: String) {
56		self.api_url = api_url;
57	}
58
59	/// 设置 GitHub 基础 URL
60	pub fn set_base_url(&mut self, base_url: String) {
61		self.base_url = base_url;
62	}
63}
64
65#[derive(Debug, Clone)]
66pub struct GitHubClient {
67	pub(crate) inner: Arc<GitHubClientInner>,
68}
69
70impl Default for GitHubClient {
71	fn default() -> Self {
72		let client = reqwest::Client::new();
73		Self {
74			inner: Arc::new(GitHubClientInner {
75				config: GitHubConfig::default(),
76				client: Arc::new(RwLock::new(Arc::new(
77					ClientBuilder::new(client)
78						.with(HeaderMiddleware)
79						.with(ResponseMiddleware)
80						.build(),
81				))),
82			}),
83		}
84	}
85}
86impl GitHubClient {
87	pub fn new() -> Self {
88		Self::default()
89	}
90
91	/// 设置反向代理
92	pub fn set_reverse_proxy(&mut self, url: &str) {
93		let clean_url = url.trim_end_matches('/');
94		let inner = Arc::make_mut(&mut self.inner);
95		let api_url = format!("{}/{}", clean_url, inner.config.api_url);
96		let base_url = format!("{}/{}", clean_url, inner.config.base_url);
97		inner.config.set_api_url(api_url);
98		inner.config.set_base_url(base_url);
99	}
100}
101
102#[async_trait]
103impl Client for GitHubClient {
104	fn set_token(&mut self, token: &str) -> Result<()> {
105		if token.is_empty() {
106			return Err(Error::TokenEmpty);
107		}
108		Arc::make_mut(&mut self.inner).config.set_token(token);
109		Ok(())
110	}
111
112	fn set_proxy(&mut self, proxy: &str) -> Result<()> {
113		let client = reqwest::Client::builder().proxy(Proxy::all(proxy)?).build()?;
114		*self.inner.client.try_write().unwrap() = Arc::new(
115			ClientBuilder::new(client).with(HeaderMiddleware).with(ResponseMiddleware).build(),
116		);
117		Ok(())
118	}
119
120	fn user(&self) -> Box<dyn User> {
121		Box::new(GitHubUser(self.inner.clone()))
122	}
123
124	fn org(&self) -> Box<dyn Org> {
125		Box::new(GitHubOrg(self.inner.clone()))
126	}
127
128	fn repo(&self) -> Box<dyn Repo> {
129		Box::new(GitHubRepo(self.inner.clone()))
130	}
131
132	fn commit(&self) -> Box<dyn Commit> {
133		Box::new(GitHubCommit(self.inner.clone()))
134	}
135
136	fn issue(&self) -> Box<dyn Issue> {
137		Box::new(GitHubIssue(self.inner.clone()))
138	}
139
140	fn release(&self) -> Box<dyn Release> {
141		Box::new(GitHubRelease(self.inner.clone()))
142	}
143}