123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103 |
- use crate::config::{self, ConfigurationError};
- use crate::github::{Event, GithubClient};
- use futures::future::BoxFuture;
- use std::fmt;
- use tokio_postgres::Client as DbClient;
- #[derive(Debug)]
- pub enum HandlerError {
- Message(String),
- Other(anyhow::Error),
- }
- impl std::error::Error for HandlerError {}
- impl fmt::Display for HandlerError {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- match self {
- HandlerError::Message(msg) => write!(f, "{}", msg),
- HandlerError::Other(_) => write!(f, "An internal error occurred."),
- }
- }
- }
- macro_rules! handlers {
- ($($name:ident = $handler:expr,)*) => {
- $(mod $name;)*
- mod notification;
- pub async fn handle(ctx: &Context, event: &Event) -> Result<(), HandlerError> {
- let config = config::get(&ctx.github, event.repo_name()).await;
- $(
- if let Some(input) = Handler::parse_input(
- &$handler, ctx, event, config.as_ref().ok().and_then(|c| c.$name.as_ref()),
- ).map_err(HandlerError::Message)? {
- let config = match &config {
- Ok(config) => config,
- Err(e @ ConfigurationError::Missing) => {
- return Err(HandlerError::Message(e.to_string()));
- }
- Err(e @ ConfigurationError::Toml(_)) => {
- return Err(HandlerError::Message(e.to_string()));
- }
- Err(e @ ConfigurationError::Http(_)) => {
- return Err(HandlerError::Other(e.clone().into()));
- }
- };
- if let Some(config) = &config.$name {
- Handler::handle_input(&$handler, ctx, config, event, input).await.map_err(HandlerError::Other)?;
- } else {
- return Err(HandlerError::Message(format!(
- "The feature `{}` is not enabled in this repository.\n\
- To enable it add its section in the `triagebot.toml` \
- in the root of the repository.",
- stringify!($name)
- )));
- }
- })*
- if let Err(e) = notification::handle(ctx, event).await {
- log::error!("failed to process event {:?} with notification handler: {:?}", event, e);
- }
- Ok(())
- }
- }
- }
- handlers! {
- assign = assign::AssignmentHandler,
- relabel = relabel::RelabelHandler,
- ping = ping::PingHandler,
- nominate = nominate::NominateHandler,
- prioritize = prioritize::PrioritizeHandler,
- major_change = major_change::MajorChangeHandler,
- //tracking_issue = tracking_issue::TrackingIssueHandler,
- }
- pub struct Context {
- pub github: GithubClient,
- pub db: DbClient,
- pub username: String,
- }
- pub trait Handler: Sync + Send {
- type Input;
- type Config;
- fn parse_input(
- &self,
- ctx: &Context,
- event: &Event,
- config: Option<&Self::Config>,
- ) -> Result<Option<Self::Input>, String>;
- fn handle_input<'a>(
- &self,
- ctx: &'a Context,
- config: &'a Self::Config,
- event: &'a Event,
- input: Self::Input,
- ) -> BoxFuture<'a, anyhow::Result<()>>;
- }
|