github_email/authors/
query.rs

1use crate::{parse_queries, GithubError};
2
3use super::*;
4
5impl Authors {
6    pub async fn query<Q>(&mut self, query: Q) -> Result<()>
7    where
8        Q: Into<AuthorQuery>,
9    {
10        match query.into() {
11            AuthorQuery::Nothing => {}
12            AuthorQuery::User(user) => collect_user_events(&user, self).await?,
13            AuthorQuery::Repo(user, repo) => collect_repo_events(&user, &repo, self).await?,
14        }
15        Ok(())
16    }
17    pub async fn query_many(&mut self, queries: &str) -> Vec<GithubError> {
18        let mut errors = vec![];
19        for query in parse_queries(queries) {
20            // info!("Query: {query:?}");
21            if let Err(e) = self.query(query).await {
22                errors.push(e)
23            }
24        }
25        errors
26    }
27}
28
29impl AuthorQuery {
30    pub fn is_none(&self) -> bool {
31        matches!(self, AuthorQuery::Nothing)
32    }
33    pub fn is_some(&self) -> bool {
34        !self.is_none()
35    }
36}
37
38impl From<&str> for AuthorQuery {
39    fn from(value: &str) -> Self {
40        let url = match value.contains("://") {
41            true => value.to_string(),
42            false => format!("https://github.com/{value}"),
43        };
44        match Url::parse(&url) {
45            Ok(o) => AuthorQuery::from(&o),
46            Err(_) => AuthorQuery::Nothing,
47        }
48    }
49}
50
51impl From<&Url> for AuthorQuery {
52    fn from(value: &Url) -> Self {
53        let path = value.path().split("/").collect::<Vec<_>>();
54        // println!("{:?} => {:?}", path, path_slice(&path));
55        match path_slice(&path) {
56            [user] => AuthorQuery::User(user.to_string()),
57            [user, repo, ..] => AuthorQuery::Repo(user.to_string(), repo.to_string()),
58            _ => AuthorQuery::Nothing,
59        }
60    }
61}
62
63fn path_slice<'v, 's>(path: &'v [&'s str]) -> &'v [&'s str] {
64    let mut l = 0;
65    let mut r = path.len();
66    for ls in path {
67        match ls.is_empty() {
68            true => l += 1,
69            false => break,
70        }
71    }
72    for rs in path.iter().rev() {
73        match rs.is_empty() {
74            true => r -= 1,
75            false => break,
76        }
77    }
78    // println!("{}..{}", l, r);
79    if l > r { &[] } else { &path[l..r] }
80}