1pub mod client;
2pub mod collaborators;
3pub mod gists;
4pub mod issues;
5pub mod labels;
6pub mod pulls;
7pub mod milestones;
8pub mod releases;
9pub mod repos;
10pub mod search;
11pub mod users;
12pub mod webhooks;
13
14use crate::models::{Comment, PrComment};
15
16#[derive(Debug, Clone)]
20pub enum StateChange<T> {
21 Changed(T),
22 Already(T),
23}
24
25pub trait AuthoredComment {
27 fn author_login(&self) -> Option<&str>;
28 fn created_at_str(&self) -> Option<&str>;
29}
30
31impl AuthoredComment for Comment {
32 fn author_login(&self) -> Option<&str> {
33 self.user.as_ref().map(|u| u.login.as_str())
34 }
35 fn created_at_str(&self) -> Option<&str> {
36 self.created_at.as_deref()
37 }
38}
39
40impl AuthoredComment for PrComment {
41 fn author_login(&self) -> Option<&str> {
42 self.user.as_ref().map(|u| u.login.as_str())
43 }
44 fn created_at_str(&self) -> Option<&str> {
45 self.created_at.as_deref()
46 }
47}
48
49pub fn resolve_latest_comment<'a, T: AuthoredComment>(
52 comments: &'a [T],
53 login: &str,
54) -> Option<&'a T> {
55 comments
56 .iter()
57 .filter(|c| c.author_login() == Some(login))
58 .max_by_key(|c| c.created_at_str().unwrap_or(""))
59}
60
61impl<T> StateChange<T> {
62 pub fn into_inner(self) -> T {
63 match self {
64 StateChange::Changed(t) | StateChange::Already(t) => t,
65 }
66 }
67
68 pub fn was_changed(&self) -> bool {
69 matches!(self, StateChange::Changed(_))
70 }
71}