1use std::{
2 collections::HashMap,
3 fmt::{Debug, Display, Formatter},
4 hash::Hash,
5};
6
7use async_trait::async_trait;
8
9pub mod github;
10
11pub mod wechat;
12
13pub mod wecom;
14
15pub mod qq;
16
17#[derive(Debug)]
18pub struct Error(String);
19
20impl Display for Error {
21 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
22 write!(f, "{}", self.0)
23 }
24}
25
26impl std::error::Error for Error {}
27
28impl From<reqwest::Error> for Error {
29 fn from(e: reqwest::Error) -> Self {
30 Self(e.to_string())
31 }
32}
33
34pub type Result<T> = std::result::Result<T, Error>;
35
36pub struct Userinfo {
37 pub unique_id: String,
38 pub name: String,
39 pub account: String,
40 pub email: Option<String>,
41 pub organization: Option<Vec<Organization>>,
42}
43
44pub struct Organization {
45 pub unique_id: String,
46 pub account: String,
47 pub name: String,
48}
49
50pub enum Client {
51 Github(github::Client),
52}
53
54pub struct Service<T>
55 where
56 T: Eq + Hash,
57{
58 clients: HashMap<T, Client>,
59}
60
61impl<T> Service<T>
62 where
63 T: Eq + Hash,
64{
65 pub fn new() -> Self {
66 Self {
67 clients: HashMap::new(),
68 }
69 }
70
71 pub fn register(&mut self, index: T, cli: Client) {
72 self.clients.insert(index, cli);
73 }
74
75 pub fn deregister(&mut self, index: T) {
76 self.clients.remove(&index);
77 }
78
79 pub async fn userinfo(&self, index: &T, code: &str) -> Result<Userinfo> {
80 let cli = self.clients.get(index).unwrap();
81 match cli {
82 Client::Github(gh) => gh.userinfo(code).await,
83 }
84 }
85}
86
87#[async_trait]
88pub trait Profile {
89 async fn userinfo(&self, code: &str) -> Result<Userinfo>;
90}
91
92#[cfg(test)]
93mod tests {
94 #[derive(Hash, Eq)]
95 enum Type {
96 Github = 0,
97 }
98
99 #[test]
100 fn test_clients() {
101 let mut mgr = super::Service::new();
102
103 let gh = super::github::Client::new("", "");
104
105 mgr.register(Type::Github, super::Client::Github(gh));
106
107 let userinfo = mgr.userinfo(Type::Github, "");
108 }
109}