diff --git a/src/bot.rs b/src/bot.rs
index 25dea32..928da9b 100644
--- a/src/bot.rs
+++ b/src/bot.rs
@@ -13,7 +13,7 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-use crate::hook::{format_hook, GitlabHook};
+use crate::hook::{format_hook, Hook};
use log::debug;
use xmpp::jid::{BareJid, Jid};
@@ -75,7 +75,7 @@ impl XmppClient {
}
}
- pub async fn hook(&mut self, wh: GitlabHook) {
+ pub async fn hook(&mut self, wh: Hook) {
debug!("Received Hook");
if let Some(display) = format_hook(&wh) {
debug!("Hook: {}", display);
diff --git a/src/error.rs b/src/error.rs
index e45c86a..14ac4b0 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -29,6 +29,7 @@ pub(crate) enum Error {
InvalidContentType,
InvalidSignature,
InvalidRequest,
+ UnsupportedHookConversion,
Hex(FromHexError),
Hmac(HmacInvalidLength),
Hyper(hyper::Error),
@@ -64,6 +65,7 @@ impl std::fmt::Display for Error {
Error::InvalidContentType => write!(fmt, "the content-type is invalid"),
Error::InvalidSignature => write!(fmt, "the signature is invalid"),
Error::InvalidRequest => write!(fmt, "the request is invalid"),
+ Error::UnsupportedHookConversion => write!(fmt, "Unable to convert hook"),
Error::Hex(e) => write!(fmt, "hex error: {}", e),
Error::Hmac(e) => write!(fmt, "hmac error: {}", e),
Error::Hyper(e) => write!(fmt, "hyper error: {}", e),
diff --git a/src/hook.rs b/src/hook.rs
index 7a649f8..32fc1df 100644
--- a/src/hook.rs
+++ b/src/hook.rs
@@ -13,35 +13,123 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
+use crate::Error;
+
pub use forgejo_hooks::Hook as ForgejoHook;
pub use gitlab::webhooks::{
IssueAction, MergeRequestAction, WebHook as GitlabHook, WikiPageAction,
};
use log::debug;
-#[derive(Debug)]
-pub enum Hook {
- Forgejo(ForgejoHook),
- Gitlab(GitlabHook),
+/// Defines a generic user that can be used for many purposes.
+#[derive(Debug, Clone)]
+pub(crate) struct User {
+ /// Name of the user
+ name: String,
}
-impl From for Hook {
- fn from(hook: GitlabHook) -> Hook {
- Hook::Gitlab(hook)
+#[derive(Debug, Clone)]
+pub(crate) struct Commit {
+ /// Commit message
+ message: String,
+ /// URL where the commit can be read at
+ url: String,
+}
+
+#[derive(Debug, Clone)]
+pub(crate) struct Repository {
+ /// Name of the project.
+ name: String,
+}
+
+#[derive(Debug, Clone)]
+pub(crate) struct Push {
+ /// Reference where commits have been pushed to.
+ ref_: String,
+ /// The event which occured.
+ object_kind: String,
+ /// Commit list.
+ commits: Vec,
+ /// Project repository.
+ repository: Repository,
+ /// Person who pushed the commits. It isn't necessarily the same as commit authors.
+ pusher: User,
+}
+
+/// Lowest common denominator struct so that we don't have to duplicate our code for each platform
+/// we support.
+#[derive(Debug)]
+pub(crate) enum Hook {
+ /// Push event
+ Push(Push),
+}
+
+impl TryFrom for Hook {
+ type Error = Error;
+
+ fn try_from(hook: GitlabHook) -> Result {
+ Ok(match hook {
+ GitlabHook::Push(push) => Hook::Push(Push {
+ ref_: push.ref_,
+ object_kind: push.object_kind,
+ commits: push
+ .commits
+ .into_iter()
+ .map(|commit| Commit {
+ message: commit.message,
+ url: commit.url,
+ })
+ .collect(),
+ repository: Repository {
+ name: push.project.name,
+ },
+ pusher: User {
+ name: push.user_name,
+ },
+ }),
+ _ => return Err(Error::UnsupportedHookConversion),
+ })
}
}
-pub fn format_hook(glh: &GitlabHook) -> Option {
- Some(match glh {
- GitlabHook::Push(push) if push.object_kind == "tag_push" => {
+impl TryFrom for Hook {
+ type Error = Error;
+
+ fn try_from(hook: ForgejoHook) -> Result {
+ Ok(match hook {
+ ForgejoHook::Push(push) => Hook::Push(Push {
+ ref_: push.ref_,
+ object_kind: String::from("push"),
+ commits: push
+ .commits
+ .into_iter()
+ .map(|commit| Commit {
+ message: commit.message,
+ url: commit.url,
+ })
+ .collect(),
+ repository: Repository {
+ name: push.repository.name,
+ },
+ pusher: User {
+ name: push.pusher.login,
+ },
+ }),
+ _ => return Err(Error::UnsupportedHookConversion),
+ })
+ }
+}
+
+pub(crate) fn format_hook(hook: &Hook) -> Option {
+ Some(match hook {
+ Hook::Push(push) if push.object_kind == "tag_push" => {
+ let ref_ = push.ref_.strip_prefix("refs/tags/").unwrap_or("?!");
format!(
"[{}] {} pushed tag {}.",
- push.project.name,
- push.user_name,
- push.ref_.strip_prefix("refs/tags/").unwrap_or("?!"),
+ push.repository.name, push.pusher.name, ref_
)
}
- GitlabHook::Push(push) => {
+ Hook::Push(push) => {
if push.ref_ != "refs/heads/main" {
// Ignore: Action not on 'main' branch
return None;
@@ -53,8 +141,8 @@ pub fn format_hook(glh: &GitlabHook) -> Option {
}
let mut text = format!(
"[{}] {} pushed {} commits to main",
- push.project.name,
- push.user_name,
+ push.repository.name,
+ push.pusher.name,
push.commits.len(),
);
// Display max 3 commits
@@ -67,109 +155,110 @@ pub fn format_hook(glh: &GitlabHook) -> Option {
}
}
text
- }
- GitlabHook::Issue(issue) => {
- let action = match issue.object_attributes.action {
- Some(IssueAction::Update) => return None,
- Some(IssueAction::Open) => "opened",
- Some(IssueAction::Close) => "closed",
- Some(IssueAction::Reopen) => "reopened",
- None => return None,
- };
- format!(
- "[{}] {} {} issue {}: {}{}",
- issue.project.name,
- issue.user.name,
- action,
- issue.object_attributes.iid,
- issue.object_attributes.title,
- issue
- .object_attributes
- .url
- .as_ref()
- .map(|url| format!(" <{}>", url))
- .unwrap_or("".to_owned())
- )
- }
- GitlabHook::MergeRequest(merge_req) => {
- let action = match merge_req.object_attributes.action {
- Some(MergeRequestAction::Update) => return None,
- Some(MergeRequestAction::Open) => "opened",
- Some(MergeRequestAction::Close) => "closed",
- Some(MergeRequestAction::Reopen) => "reopened",
- Some(MergeRequestAction::Merge) => "merged",
- None => return None,
- _ => {
- log::warn!(
- "Unsupported merge request action: {:?}",
- merge_req.object_attributes.action
- );
- return None;
- }
- };
- format!(
- "[{}] {} {} merge request {}: {}{}",
- merge_req.project.name,
- merge_req.user.name,
- action,
- merge_req.object_attributes.iid,
- merge_req.object_attributes.title,
- merge_req
- .object_attributes
- .url
- .as_ref()
- .map(|url| format!(" <{}>", url))
- .unwrap_or("".to_owned())
- )
- }
- GitlabHook::Note(note) => {
- if let Some(_) = note.snippet {
- return None;
- }
- if let Some(commit) = ¬e.commit {
- format!(
- "[{}] {} commented on commit {:?} <{}>",
- note.project.name, note.user.name, commit.id, commit.url,
- )
- } else if let Some(issue) = ¬e.issue {
- format!(
- "[{}] {} commented on issue {}: {} <{}>",
- note.project.name,
- note.user.name,
- issue.iid,
- issue.title,
- note.object_attributes.url,
- )
- } else if let Some(mr) = ¬e.merge_request {
- format!(
- "[{}] {} commented on merge request {}: {} <{}>",
- note.project.name, note.user.name, mr.iid, mr.title, note.object_attributes.url,
- )
- } else {
- unreachable!()
- }
- }
- GitlabHook::Build(build) => {
- println!("Build: {:?}", build);
- return None;
- }
- GitlabHook::WikiPage(page) => {
- let action = match page.object_attributes.action {
- WikiPageAction::Update => "updated",
- WikiPageAction::Create => "created",
- };
- format!(
- "[{}] {} {} wiki page {} <{}>",
- page.project.name,
- page.user.name,
- action,
- page.object_attributes.title,
- page.object_attributes.url,
- )
- }
- _glh => {
- debug!("Hook not supported");
- return None;
- }
+ } /*
+ Hook::Issue(issue) => {
+ let action = match issue.object_attributes.action {
+ Some(IssueAction::Update) => return None,
+ Some(IssueAction::Open) => "opened",
+ Some(IssueAction::Close) => "closed",
+ Some(IssueAction::Reopen) => "reopened",
+ None => return None,
+ };
+ format!(
+ "[{}] {} {} issue {}: {}{}",
+ issue.project.name,
+ issue.user.name,
+ action,
+ issue.object_attributes.iid,
+ issue.object_attributes.title,
+ issue
+ .object_attributes
+ .url
+ .as_ref()
+ .map(|url| format!(" <{}>", url))
+ .unwrap_or("".to_owned())
+ )
+ }
+ Hook::MergeRequest(merge_req) => {
+ let action = match merge_req.object_attributes.action {
+ Some(MergeRequestAction::Update) => return None,
+ Some(MergeRequestAction::Open) => "opened",
+ Some(MergeRequestAction::Close) => "closed",
+ Some(MergeRequestAction::Reopen) => "reopened",
+ Some(MergeRequestAction::Merge) => "merged",
+ None => return None,
+ _ => {
+ log::warn!(
+ "Unsupported merge request action: {:?}",
+ merge_req.object_attributes.action
+ );
+ return None;
+ }
+ };
+ format!(
+ "[{}] {} {} merge request {}: {}{}",
+ merge_req.project.name,
+ merge_req.user.name,
+ action,
+ merge_req.object_attributes.iid,
+ merge_req.object_attributes.title,
+ merge_req
+ .object_attributes
+ .url
+ .as_ref()
+ .map(|url| format!(" <{}>", url))
+ .unwrap_or("".to_owned())
+ )
+ }
+ Hook::Note(note) => {
+ if let Some(_) = note.snippet {
+ return None;
+ }
+ if let Some(commit) = ¬e.commit {
+ format!(
+ "[{}] {} commented on commit {:?} <{}>",
+ note.project.name, note.user.name, commit.id, commit.url,
+ )
+ } else if let Some(issue) = ¬e.issue {
+ format!(
+ "[{}] {} commented on issue {}: {} <{}>",
+ note.project.name,
+ note.user.name,
+ issue.iid,
+ issue.title,
+ note.object_attributes.url,
+ )
+ } else if let Some(mr) = ¬e.merge_request {
+ format!(
+ "[{}] {} commented on merge request {}: {} <{}>",
+ note.project.name, note.user.name, mr.iid, mr.title, note.object_attributes.url,
+ )
+ } else {
+ unreachable!()
+ }
+ }
+ Hook::Build(build) => {
+ println!("Build: {:?}", build);
+ return None;
+ }
+ Hook::WikiPage(page) => {
+ let action = match page.object_attributes.action {
+ WikiPageAction::Update => "updated",
+ WikiPageAction::Create => "created",
+ };
+ format!(
+ "[{}] {} {} wiki page {} <{}>",
+ page.project.name,
+ page.user.name,
+ action,
+ page.object_attributes.title,
+ page.object_attributes.url,
+ )
+ }
+ _ => {
+ debug!("Hook not supported");
+ return None;
+ }
+ */
})
}
diff --git a/src/main.rs b/src/main.rs
index a054f24..d6d0157 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -91,7 +91,7 @@ async fn main() -> Result {
}
}
wh = value_rx.recv() => {
- if let Some(Hook::Gitlab(hook)) = wh {
+ if let Some(hook) = wh {
client.hook(hook).await
}
}
diff --git a/src/web.rs b/src/web.rs
index 9feeabe..5892d66 100644
--- a/src/web.rs
+++ b/src/web.rs
@@ -68,7 +68,7 @@ async fn hooks_inner(req: Request, secret: &str) -> Result, secret: &str) -> Result {
debug!("Passed: {:?}", wh);
-
- match wh {
- hook @ Hook::Gitlab(_) => value_tx.lock().unwrap().send(hook).unwrap(),
- _ => (),
- }
-
+ value_tx.lock().unwrap().send(wh).unwrap();
Ok(Response::new(Full::new(Bytes::from("Hello, World!"))))
}
Err(err) => error_res(err),