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.repos(&self.owner, &self.repo).get().await.map_err(|e| {
83 MiyabiError::GitHub(format!(
84 "Failed to get repository {}/{}: {}",
85 self.owner, self.repo, e
86 ))
87 })
88 }
89}
90
91#[cfg(test)]
92mod tests {
93 use super::*;
94
95 #[tokio::test]
96 async fn test_client_creation() {
97 let client = GitHubClient::new("ghp_test", "owner", "repo");
99 assert!(client.is_ok());
100
101 let client = client.unwrap();
102 assert_eq!(client.owner(), "owner");
103 assert_eq!(client.repo(), "repo");
104 assert_eq!(client.full_name(), "owner/repo");
105 }
106
107 #[tokio::test]
108 async fn test_client_cloning() {
109 let client = GitHubClient::new("ghp_test", "owner", "repo").unwrap();
110 let _cloned = client.clone();
111 assert_eq!(client.owner(), "owner");
112 }
113
114 }