1use miyabi_types::error::{MiyabiError, Result};
6use octocrab::Octocrab;
7
8#[derive(Clone)]
10pub struct GitHubClient {
11 pub(crate) client: Octocrab,
12 pub(crate) owner: String,
13 pub(crate) repo: String,
14}
15
16impl GitHubClient {
17 pub fn new(
32 token: impl Into<String>,
33 owner: impl Into<String>,
34 repo: impl Into<String>,
35 ) -> Result<Self> {
36 let client = Octocrab::builder()
37 .personal_token(token.into())
38 .build()
39 .map_err(|e| MiyabiError::GitHub(format!("Failed to build Octocrab client: {}", e)))?;
40
41 Ok(Self {
42 client,
43 owner: owner.into(),
44 repo: repo.into(),
45 })
46 }
47
48 pub fn octocrab(&self) -> &Octocrab {
50 &self.client
51 }
52
53 pub fn owner(&self) -> &str {
55 &self.owner
56 }
57
58 pub fn repo(&self) -> &str {
60 &self.repo
61 }
62
63 pub fn full_name(&self) -> String {
65 format!("{}/{}", self.owner, self.repo)
66 }
67
68 pub async fn verify_auth(&self) -> Result<String> {
70 let user = self
71 .client
72 .current()
73 .user()
74 .await
75 .map_err(|e| MiyabiError::GitHub(format!("Authentication failed: {}", e)))?;
76
77 Ok(user.login)
78 }
79
80 pub async fn get_repository(&self) -> Result<octocrab::models::Repository> {
82 self.client
83 .repos(&self.owner, &self.repo)
84 .get()
85 .await
86 .map_err(|e| {
87 MiyabiError::GitHub(format!(
88 "Failed to get repository {}/{}: {}",
89 self.owner, self.repo, e
90 ))
91 })
92 }
93}
94
95#[cfg(test)]
96mod tests {
97 use super::*;
98
99 #[tokio::test]
100 async fn test_client_creation() {
101 let client = GitHubClient::new("ghp_test", "owner", "repo");
103 assert!(client.is_ok());
104
105 let client = client.unwrap();
106 assert_eq!(client.owner(), "owner");
107 assert_eq!(client.repo(), "repo");
108 assert_eq!(client.full_name(), "owner/repo");
109 }
110
111 #[tokio::test]
112 async fn test_client_cloning() {
113 let client = GitHubClient::new("ghp_test", "owner", "repo").unwrap();
114 let _cloned = client.clone();
115 assert_eq!(client.owner(), "owner");
116 }
117
118 }