Skip to content

Commit

Permalink
feat: Add a notification component
Browse files Browse the repository at this point in the history
  • Loading branch information
baerwang committed Apr 17, 2024
1 parent 10e9860 commit 80f7fe9
Show file tree
Hide file tree
Showing 9 changed files with 1,073 additions and 24 deletions.
982 changes: 974 additions & 8 deletions Cargo.lock

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,4 @@ serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
anyhow = "1.0"
toml = "0.8.8"
notify-rust = "4"
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,5 @@
*/

pub mod conf;
pub mod notification;
pub mod plugins;
6 changes: 4 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
* limitations under the License.
*/

use std::collections::HashMap;
use std::fs;

use flexible::conf::config::ConfigData;
Expand All @@ -37,16 +38,17 @@ fn main() {

let token = config.token.as_str();
let plugin = config.plugin.as_str();
let reviews: HashMap<String, ()> = config.reviews.iter().map(|key| (key.clone(), ())).collect();

config.owners.iter().for_each(|owner| {
let api = get_api(plugin, owner.name.clone());
let api = get_api(plugin, owner.name.clone(), reviews.clone());
owner.repos.iter().for_each(|repo| {
_ = api.execute(token, repo.as_str());
})
});

for (org, repos) in &config.orgs {
let api = get_api(plugin, org.clone());
let api = get_api(plugin, org.clone(), reviews.clone());
for repo in repos {
_ = api.execute(token, repo.as_str());
}
Expand Down
18 changes: 18 additions & 0 deletions src/notification/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

pub mod notify;
27 changes: 27 additions & 0 deletions src/notification/notify.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

use notify_rust::Notification;

pub fn notify(_: &str, title: &str, link: &str) {
_ = Notification::new()
.summary("New PR review")
.body(format!("{}\n{}", title, link).as_str())
.appname("flexible")
.timeout(1)
.show();
}
8 changes: 7 additions & 1 deletion src/plugins/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,13 @@

use reqwest::header::HeaderMap;

pub struct PullRequest {
pub title: String,
pub number: i64,
}

pub trait Api {
fn domain(&self) -> &str;
fn api(&self) -> &str;
fn execute(&self, token: &str, repo: &str) -> Result<(), anyhow::Error>;
fn headers(&self, token: &str) -> HeaderMap;
fn repo(&self, repo: &str) -> String;
Expand All @@ -27,4 +32,5 @@ pub trait Api {
fn pull_requests(&self, repo: &str) -> String;
fn issues(&self, repo: &str) -> String;
fn reviews(&self, repo: &str, number: i64) -> String;
fn notify(&self, repo: &str, content: &str, pr: PullRequest);
}
47 changes: 36 additions & 11 deletions src/plugins/github.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
use std::collections::HashMap;
use std::string::String;

use reqwest::header::{HeaderMap, ACCEPT, AUTHORIZATION, USER_AGENT};
use serde::Deserialize;

use crate::notification::notify::notify;
use crate::plugins::api::Api;
use crate::plugins::api::PullRequest as PR;
use crate::plugins::client;

pub struct GitHub {
pub owner: String,
pub reviews: HashMap<String, ()>,
}

impl GitHub {
pub fn new(owner: String) -> Self {
GitHub { owner }
pub fn new(owner: String, reviews: HashMap<String, ()>) -> Self {
GitHub { owner, reviews }
}
}

Expand All @@ -28,11 +32,12 @@ struct Reviews {

#[derive(Debug, Deserialize)]
struct PullRequest {
title: String,
number: i64,
}

impl Api for GitHub {
fn domain(&self) -> &str {
fn api(&self) -> &str {
"https://api.github.com"
}

Expand All @@ -43,8 +48,15 @@ impl Api for GitHub {
let reviews_data = client(self.reviews(repo, pr.number), self.headers(token))?;
let reviews: Reviews = serde_json::from_str(&reviews_data)?;
reviews.users.iter().for_each(|user| {
if user.login == self.owner {
println!("{}: {}", repo, pr.number);
if self.reviews.contains_key(user.login.as_str()) {
self.notify(
repo,
"",
PR {
title: pr.title.clone(),
number: pr.number,
},
)
}
});
}
Expand All @@ -60,38 +72,51 @@ impl Api for GitHub {
}

fn repo(&self, repo: &str) -> String {
format!("{}/users/{repo}/repos?page=1&per_page=100", self.domain())
format!("{}/users/{repo}/repos?page=1&per_page=100", self.api())
}

fn repos(&self) -> String {
format!(
"{}/users/{}/repos?page=1&per_page=100",
self.domain(),
self.api(),
self.owner
)
}

fn org_repos(&self) -> String {
format!(
"{}/orgs/{}/repos?page=1&per_page=100",
self.domain(),
self.api(),
self.owner
)
}

fn pull_requests(&self, repo: &str) -> String {
format!("{}/repos/{}/{repo}/pulls", self.domain(), self.owner)
format!("{}/repos/{}/{repo}/pulls", self.api(), self.owner)
}

fn issues(&self, repo: &str) -> String {
format!("{}/repos/{}/{repo}/issues", self.domain(), self.owner)
format!("{}/repos/{}/{repo}/issues", self.api(), self.owner)
}

fn reviews(&self, repo: &str, number: i64) -> String {
format!(
"{}/repos/{}/{repo}/pulls/{number}/requested_reviewers",
self.domain(),
self.api(),
self.owner
)
}
fn notify(&self, repo: &str, _: &str, pr: PR) {
notify(
repo,
pr.title.as_str(),
format!(
"{}/repos/{}/{repo}/pull/{}",
self.api(),
self.owner,
pr.number
)
.as_str(),
)
}
}
7 changes: 5 additions & 2 deletions src/plugins/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,18 @@
* limitations under the License.
*/

use std::collections::HashMap;

use reqwest::header::HeaderMap;

use crate::plugins::api::Api;

mod api;
mod github;

pub fn get_api(api: &str, owner: String) -> Box<dyn Api> {
pub fn get_api(api: &str, owner: String, reviews: HashMap<String, ()>) -> Box<dyn Api> {
match api {
"github" => Box::new(github::GitHub::new(owner)),
"github" => Box::new(github::GitHub::new(owner, reviews)),
_ => panic!("Unsupported"),
}
}
Expand All @@ -33,6 +35,7 @@ pub fn client(url: String, headers: HeaderMap) -> Result<String, reqwest::Error>
let resp = reqwest::blocking::Client::new()
.get(url)
.headers(headers)
.timeout(std::time::Duration::from_secs(3))
.send()?
.text()?;
Ok(resp)
Expand Down

0 comments on commit 80f7fe9

Please sign in to comment.