sourcehut-mirror-bridge/src/webhook.rs

115 lines
3.0 KiB
Rust

use anyhow::Result;
use cynic::{GraphQlResponse, MutationBuilder};
#[cynic::schema("sourcehut")]
mod schema {}
#[derive(cynic::QueryVariables, Debug)]
struct CreateWebhookVariables {
url: String,
}
#[derive(cynic::QueryFragment, Debug)]
#[cynic(graphql_type = "Mutation", variables = "CreateWebhookVariables")]
struct CreateWebhook {
#[arguments(config: { events: ["REPO_UPDATE"], query: r#"query {
webhook {
uuid
event
date
... on RepositoryEvent {
repository {
name
updated
}
}
}
}"#, url: $url })]
create_user_webhook: WebhookSubscription,
}
#[derive(cynic::QueryFragment, Debug)]
struct WebhookSubscription {
id: i32,
}
#[derive(cynic::QueryVariables, Debug)]
struct DeleteWebhookVariables {
id: i32,
}
#[derive(cynic::QueryFragment, Debug)]
#[cynic(graphql_type = "Mutation", variables = "DeleteWebhookVariables")]
struct DeleteWebhook {
#[arguments(id: $id)]
delete_user_webhook: WebhookSubscription,
}
pub struct SourceHutAPI {
api_endpoint: String,
token: String,
webhook_id: Option<i32>,
}
fn parse_gql_response(response: GraphQlResponse<WebhookSubscription>) -> Result<i32> {
match response.data {
Some(data) => Ok(data.id),
None => {
// Check for errors
match response.errors {
Some(errors) => Err(anyhow::anyhow!(errors
.iter()
.map(|e| e.to_string())
.collect::<Vec<String>>()
.join("\n"))),
None => Err(anyhow::anyhow!("Unknown error")),
}
}
}
}
impl SourceHutAPI {
pub fn new(api_endpoint: &str, token: &str) -> Self {
Self {
api_endpoint: api_endpoint.to_string(),
token: token.to_string(),
webhook_id: None,
}
}
pub fn init_webhook(&mut self, url: &str) -> Result<()> {
let operation = CreateWebhook::build(CreateWebhookVariables {
url: url.to_string(),
});
let response = ureq::post(&self.api_endpoint)
.set("Authorization", &format!("Bearer {}", &self.token))
.send_json(&operation)?
.into_json::<GraphQlResponse<WebhookSubscription>>()?;
let webhook_id = parse_gql_response(response)?;
self.webhook_id = Some(webhook_id);
Ok(())
}
fn delete_webhook(&self, id: i32) -> Result<i32> {
let operation = DeleteWebhook::build(DeleteWebhookVariables { id });
let response = ureq::post(&self.api_endpoint)
.set("Authorization", &format!("Bearer {}", &self.token))
.send_json(&operation)?
.into_json::<GraphQlResponse<WebhookSubscription>>()?;
parse_gql_response(response)
}
}
impl Drop for SourceHutAPI {
fn drop(&mut self) {
if let Some(id) = self.webhook_id {
if let Err(e) = self.delete_webhook(id) {
println!("Failed to delete webhook: {}", e);
}
}
}
}