handlers.rs 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. use crate::config::{self, ConfigurationError};
  2. use crate::github::{Event, GithubClient};
  3. use failure::Error;
  4. use futures::future::BoxFuture;
  5. use std::fmt;
  6. #[derive(Debug)]
  7. pub enum HandlerError {
  8. Message(String),
  9. Other(Error),
  10. }
  11. impl std::error::Error for HandlerError {}
  12. impl fmt::Display for HandlerError {
  13. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  14. match self {
  15. HandlerError::Message(msg) => write!(f, "{}", msg),
  16. HandlerError::Other(_) => write!(f, "An internal error occurred."),
  17. }
  18. }
  19. }
  20. macro_rules! handlers {
  21. ($($name:ident = $handler:expr,)*) => {
  22. $(mod $name;)*
  23. pub async fn handle(ctx: &Context, event: &Event) -> Result<(), HandlerError> {
  24. $(
  25. if let Some(input) = Handler::parse_input(
  26. &$handler, ctx, event).map_err(HandlerError::Message)? {
  27. let config = match config::get(&ctx.github, event.repo_name()).await {
  28. Ok(config) => config,
  29. Err(e @ ConfigurationError::Missing) => {
  30. return Err(HandlerError::Message(e.to_string()));
  31. }
  32. Err(e @ ConfigurationError::Toml(_)) => {
  33. return Err(HandlerError::Message(e.to_string()));
  34. }
  35. Err(e @ ConfigurationError::Http(_)) => {
  36. return Err(HandlerError::Other(e.into()));
  37. }
  38. };
  39. if let Some(config) = &config.$name {
  40. Handler::handle_input(&$handler, ctx, config, event, input).await.map_err(HandlerError::Other)?;
  41. } else {
  42. return Err(HandlerError::Message(format!(
  43. "The feature `{}` is not enabled in this repository.\n\
  44. To enable it add its section in the `triagebot.toml` \
  45. in the root of the repository.",
  46. stringify!($name)
  47. )));
  48. }
  49. })*
  50. Ok(())
  51. }
  52. }
  53. }
  54. handlers! {
  55. assign = assign::AssignmentHandler,
  56. relabel = relabel::RelabelHandler,
  57. //tracking_issue = tracking_issue::TrackingIssueHandler,
  58. }
  59. pub struct Context {
  60. pub github: GithubClient,
  61. pub username: String,
  62. }
  63. pub trait Handler: Sync + Send {
  64. type Input;
  65. type Config;
  66. fn parse_input(&self, ctx: &Context, event: &Event) -> Result<Option<Self::Input>, String>;
  67. fn handle_input<'a>(
  68. &self,
  69. ctx: &'a Context,
  70. config: &'a Self::Config,
  71. event: &'a Event,
  72. input: Self::Input,
  73. ) -> BoxFuture<'a, Result<(), Error>>;
  74. }