#![allow(clippy::all, unused_imports, dead_code)]
use crate::{Actor, ActorBehavior, ClientBuilderExt, Message, Port};
use anyhow::{Error, Result};
use reflow_actor::{message::EncodableValue, ActorContext};
use reflow_actor_macro::actor;
use serde_json::{json, Value};
use std::collections::HashMap;
use std::time::Duration;
const BASE_URL: &str = "https://api.notion.com/v1";
const ENV_KEY: &str = "NOTION_API_KEY";
fn apply_auth(
config: &reflow_actor::ActorConfig,
mut builder: reqwest::RequestBuilder,
) -> Result<reqwest::RequestBuilder> {
let credential = config
.get_config_or_env(ENV_KEY)
.ok_or_else(|| anyhow::anyhow!("Missing env var: {}", ENV_KEY))?;
builder = builder.header("Authorization", format!("Bearer {}", credential));
Ok(builder)
}
#[actor(
NotionCreatePageActor,
inports::<100>(parent, properties),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn notion_create_page(context: ActorContext) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let endpoint = "/pages".to_string();
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout_compat(Duration::from_secs(30))
.build()?;
let mut builder = client.post(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
let mut body = serde_json::Map::new();
if let Some(val) = inputs.get("parent") {
body.insert("parent".to_string(), val.clone().into());
}
if let Some(val) = inputs.get("properties") {
body.insert("properties".to_string(), val.clone().into());
}
if !body.is_empty() {
builder = builder.json(&serde_json::Value::Object(body));
}
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert(
"error".to_string(),
Message::Error(format!("POST /pages failed: {}", e).into()),
);
}
}
Ok(output)
}
#[actor(
NotionReadPageActor,
inports::<100>(page_id),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn notion_read_page(context: ActorContext) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let mut endpoint = "/pages/{page_id}".to_string();
if let Some(val) = inputs.get("page_id") {
endpoint = endpoint.replace("{{page_id}}", &super::message_to_str(val));
}
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout_compat(Duration::from_secs(30))
.build()?;
let mut builder = client.get(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert(
"error".to_string(),
Message::Error(format!("GET /pages/{{page_id}} failed: {}", e).into()),
);
}
}
Ok(output)
}
#[actor(
NotionSearchPagesActor,
inports::<100>(query, filter),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn notion_search_pages(context: ActorContext) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let endpoint = "/search".to_string();
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout_compat(Duration::from_secs(30))
.build()?;
let mut builder = client.post(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
let mut body = serde_json::Map::new();
if let Some(val) = inputs.get("query") {
body.insert("query".to_string(), val.clone().into());
}
if let Some(val) = inputs.get("filter") {
body.insert("filter".to_string(), val.clone().into());
}
if !body.is_empty() {
builder = builder.json(&serde_json::Value::Object(body));
}
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert(
"error".to_string(),
Message::Error(format!("POST /search failed: {}", e).into()),
);
}
}
Ok(output)
}
#[actor(
NotionUpdatePageActor,
inports::<100>(page_id, properties, archived, icon, cover, Notion_Version),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn notion_update_page(context: ActorContext) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let mut endpoint = "/pages/{page_id}".to_string();
if let Some(val) = inputs.get("page_id") {
endpoint = endpoint.replace("{{page_id}}", &super::message_to_str(val));
}
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout_compat(Duration::from_secs(30))
.build()?;
let mut builder = client.patch(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
if let Some(val) = inputs.get("Notion_Version") {
builder = builder.header("Notion-Version", super::message_to_str(val));
}
let mut body = serde_json::Map::new();
if let Some(val) = inputs.get("properties") {
body.insert("properties".to_string(), val.clone().into());
}
if let Some(val) = inputs.get("archived") {
body.insert("archived".to_string(), val.clone().into());
}
if let Some(val) = inputs.get("icon") {
body.insert("icon".to_string(), val.clone().into());
}
if let Some(val) = inputs.get("cover") {
body.insert("cover".to_string(), val.clone().into());
}
if !body.is_empty() {
builder = builder.json(&serde_json::Value::Object(body));
}
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert(
"error".to_string(),
Message::Error(format!("PATCH /pages/{{page_id}} failed: {}", e).into()),
);
}
}
Ok(output)
}
#[actor(
NotionReadPagePropertyActor,
inports::<100>(page_id, property_id, page_size, start_cursor, Notion_Version),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn notion_read_page_property(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let mut endpoint = "/pages/{page_id}/properties/{property_id}".to_string();
if let Some(val) = inputs.get("page_id") {
endpoint = endpoint.replace("{{page_id}}", &super::message_to_str(val));
}
if let Some(val) = inputs.get("property_id") {
endpoint = endpoint.replace("{{property_id}}", &super::message_to_str(val));
}
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout_compat(Duration::from_secs(30))
.build()?;
let mut builder = client.get(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
let mut query_pairs: Vec<(&str, String)> = Vec::new();
if let Some(val) = inputs.get("page_size") {
query_pairs.push(("page_size", super::message_to_str(val)));
}
if let Some(val) = inputs.get("start_cursor") {
query_pairs.push(("start_cursor", super::message_to_str(val)));
}
if !query_pairs.is_empty() {
builder = builder.query(&query_pairs);
}
if let Some(val) = inputs.get("Notion_Version") {
builder = builder.header("Notion-Version", super::message_to_str(val));
}
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert(
"error".to_string(),
Message::Error(
format!(
"GET /pages/{{page_id}}/properties/{{property_id}} failed: {}",
e
)
.into(),
),
);
}
}
Ok(output)
}
#[actor(
NotionCreateDatabaseActor,
inports::<100>(parent, title, properties, icon, cover, is_inline, Notion_Version),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn notion_create_database(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let endpoint = "/databases".to_string();
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout_compat(Duration::from_secs(30))
.build()?;
let mut builder = client.post(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
if let Some(val) = inputs.get("Notion_Version") {
builder = builder.header("Notion-Version", super::message_to_str(val));
}
let mut body = serde_json::Map::new();
if let Some(val) = inputs.get("parent") {
body.insert("parent".to_string(), val.clone().into());
}
if let Some(val) = inputs.get("title") {
body.insert("title".to_string(), val.clone().into());
}
if let Some(val) = inputs.get("properties") {
body.insert("properties".to_string(), val.clone().into());
}
if let Some(val) = inputs.get("icon") {
body.insert("icon".to_string(), val.clone().into());
}
if let Some(val) = inputs.get("cover") {
body.insert("cover".to_string(), val.clone().into());
}
if let Some(val) = inputs.get("is_inline") {
body.insert("is_inline".to_string(), val.clone().into());
}
if !body.is_empty() {
builder = builder.json(&serde_json::Value::Object(body));
}
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert(
"error".to_string(),
Message::Error(format!("POST /databases failed: {}", e).into()),
);
}
}
Ok(output)
}
#[actor(
NotionReadDatabaseActor,
inports::<100>(database_id, Notion_Version),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn notion_read_database(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let mut endpoint = "/databases/{database_id}".to_string();
if let Some(val) = inputs.get("database_id") {
endpoint = endpoint.replace("{{database_id}}", &super::message_to_str(val));
}
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout_compat(Duration::from_secs(30))
.build()?;
let mut builder = client.get(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
if let Some(val) = inputs.get("Notion_Version") {
builder = builder.header("Notion-Version", super::message_to_str(val));
}
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert(
"error".to_string(),
Message::Error(format!("GET /databases/{{database_id}} failed: {}", e).into()),
);
}
}
Ok(output)
}
#[actor(
NotionUpdateDatabaseActor,
inports::<100>(database_id, title, properties, archived, icon, cover, Notion_Version),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn notion_update_database(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let mut endpoint = "/databases/{database_id}".to_string();
if let Some(val) = inputs.get("database_id") {
endpoint = endpoint.replace("{{database_id}}", &super::message_to_str(val));
}
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout_compat(Duration::from_secs(30))
.build()?;
let mut builder = client.patch(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
if let Some(val) = inputs.get("Notion_Version") {
builder = builder.header("Notion-Version", super::message_to_str(val));
}
let mut body = serde_json::Map::new();
if let Some(val) = inputs.get("title") {
body.insert("title".to_string(), val.clone().into());
}
if let Some(val) = inputs.get("properties") {
body.insert("properties".to_string(), val.clone().into());
}
if let Some(val) = inputs.get("archived") {
body.insert("archived".to_string(), val.clone().into());
}
if let Some(val) = inputs.get("icon") {
body.insert("icon".to_string(), val.clone().into());
}
if let Some(val) = inputs.get("cover") {
body.insert("cover".to_string(), val.clone().into());
}
if !body.is_empty() {
builder = builder.json(&serde_json::Value::Object(body));
}
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert(
"error".to_string(),
Message::Error(format!("PATCH /databases/{{database_id}} failed: {}", e).into()),
);
}
}
Ok(output)
}
#[actor(
NotionSearchDatabaseActor,
inports::<100>(database_id, filter, sorts, start_cursor, page_size, Notion_Version),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn notion_search_database(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let mut endpoint = "/databases/{database_id}/query".to_string();
if let Some(val) = inputs.get("database_id") {
endpoint = endpoint.replace("{{database_id}}", &super::message_to_str(val));
}
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout_compat(Duration::from_secs(30))
.build()?;
let mut builder = client.post(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
if let Some(val) = inputs.get("Notion_Version") {
builder = builder.header("Notion-Version", super::message_to_str(val));
}
let mut body = serde_json::Map::new();
if let Some(val) = inputs.get("filter") {
body.insert("filter".to_string(), val.clone().into());
}
if let Some(val) = inputs.get("sorts") {
body.insert("sorts".to_string(), val.clone().into());
}
if let Some(val) = inputs.get("start_cursor") {
body.insert("start_cursor".to_string(), val.clone().into());
}
if let Some(val) = inputs.get("page_size") {
body.insert("page_size".to_string(), val.clone().into());
}
if !body.is_empty() {
builder = builder.json(&serde_json::Value::Object(body));
}
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert(
"error".to_string(),
Message::Error(
format!("POST /databases/{{database_id}}/query failed: {}", e).into(),
),
);
}
}
Ok(output)
}
#[actor(
NotionReadBlockActor,
inports::<100>(block_id, Notion_Version),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn notion_read_block(context: ActorContext) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let mut endpoint = "/blocks/{block_id}".to_string();
if let Some(val) = inputs.get("block_id") {
endpoint = endpoint.replace("{{block_id}}", &super::message_to_str(val));
}
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout_compat(Duration::from_secs(30))
.build()?;
let mut builder = client.get(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
if let Some(val) = inputs.get("Notion_Version") {
builder = builder.header("Notion-Version", super::message_to_str(val));
}
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert(
"error".to_string(),
Message::Error(format!("GET /blocks/{{block_id}} failed: {}", e).into()),
);
}
}
Ok(output)
}
#[actor(
NotionUpdateBlockActor,
inports::<100>(block_id, archived, Notion_Version),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn notion_update_block(context: ActorContext) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let mut endpoint = "/blocks/{block_id}".to_string();
if let Some(val) = inputs.get("block_id") {
endpoint = endpoint.replace("{{block_id}}", &super::message_to_str(val));
}
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout_compat(Duration::from_secs(30))
.build()?;
let mut builder = client.patch(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
if let Some(val) = inputs.get("Notion_Version") {
builder = builder.header("Notion-Version", super::message_to_str(val));
}
let mut body = serde_json::Map::new();
if let Some(val) = inputs.get("archived") {
body.insert("archived".to_string(), val.clone().into());
}
if !body.is_empty() {
builder = builder.json(&serde_json::Value::Object(body));
}
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert(
"error".to_string(),
Message::Error(format!("PATCH /blocks/{{block_id}} failed: {}", e).into()),
);
}
}
Ok(output)
}
#[actor(
NotionDeleteBlockActor,
inports::<100>(block_id, Notion_Version),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn notion_delete_block(context: ActorContext) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let mut endpoint = "/blocks/{block_id}".to_string();
if let Some(val) = inputs.get("block_id") {
endpoint = endpoint.replace("{{block_id}}", &super::message_to_str(val));
}
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout_compat(Duration::from_secs(30))
.build()?;
let mut builder = client.delete(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
if let Some(val) = inputs.get("Notion_Version") {
builder = builder.header("Notion-Version", super::message_to_str(val));
}
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert(
"error".to_string(),
Message::Error(format!("DELETE /blocks/{{block_id}} failed: {}", e).into()),
);
}
}
Ok(output)
}
#[actor(
NotionListBlockChildrenActor,
inports::<100>(block_id, start_cursor, page_size, Notion_Version),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn notion_list_block_children(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let mut endpoint = "/blocks/{block_id}/children".to_string();
if let Some(val) = inputs.get("block_id") {
endpoint = endpoint.replace("{{block_id}}", &super::message_to_str(val));
}
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout_compat(Duration::from_secs(30))
.build()?;
let mut builder = client.get(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
let mut query_pairs: Vec<(&str, String)> = Vec::new();
if let Some(val) = inputs.get("start_cursor") {
query_pairs.push(("start_cursor", super::message_to_str(val)));
}
if let Some(val) = inputs.get("page_size") {
query_pairs.push(("page_size", super::message_to_str(val)));
}
if !query_pairs.is_empty() {
builder = builder.query(&query_pairs);
}
if let Some(val) = inputs.get("Notion_Version") {
builder = builder.header("Notion-Version", super::message_to_str(val));
}
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert(
"error".to_string(),
Message::Error(format!("GET /blocks/{{block_id}}/children failed: {}", e).into()),
);
}
}
Ok(output)
}
#[actor(
NotionCreateBlockChildrenActor,
inports::<100>(block_id, children, after, Notion_Version),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn notion_create_block_children(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let mut endpoint = "/blocks/{block_id}/children".to_string();
if let Some(val) = inputs.get("block_id") {
endpoint = endpoint.replace("{{block_id}}", &super::message_to_str(val));
}
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout_compat(Duration::from_secs(30))
.build()?;
let mut builder = client.patch(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
if let Some(val) = inputs.get("Notion_Version") {
builder = builder.header("Notion-Version", super::message_to_str(val));
}
let mut body = serde_json::Map::new();
if let Some(val) = inputs.get("children") {
body.insert("children".to_string(), val.clone().into());
}
if let Some(val) = inputs.get("after") {
body.insert("after".to_string(), val.clone().into());
}
if !body.is_empty() {
builder = builder.json(&serde_json::Value::Object(body));
}
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert(
"error".to_string(),
Message::Error(format!("PATCH /blocks/{{block_id}}/children failed: {}", e).into()),
);
}
}
Ok(output)
}
#[actor(
NotionReadUserActor,
inports::<100>(user_id, Notion_Version),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn notion_read_user(context: ActorContext) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let mut endpoint = "/users/{user_id}".to_string();
if let Some(val) = inputs.get("user_id") {
endpoint = endpoint.replace("{{user_id}}", &super::message_to_str(val));
}
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout_compat(Duration::from_secs(30))
.build()?;
let mut builder = client.get(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
if let Some(val) = inputs.get("Notion_Version") {
builder = builder.header("Notion-Version", super::message_to_str(val));
}
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert(
"error".to_string(),
Message::Error(format!("GET /users/{{user_id}} failed: {}", e).into()),
);
}
}
Ok(output)
}
#[actor(
NotionListUsersActor,
inports::<100>(start_cursor, page_size, Notion_Version),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn notion_list_users(context: ActorContext) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let endpoint = "/users".to_string();
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout_compat(Duration::from_secs(30))
.build()?;
let mut builder = client.get(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
let mut query_pairs: Vec<(&str, String)> = Vec::new();
if let Some(val) = inputs.get("start_cursor") {
query_pairs.push(("start_cursor", super::message_to_str(val)));
}
if let Some(val) = inputs.get("page_size") {
query_pairs.push(("page_size", super::message_to_str(val)));
}
if !query_pairs.is_empty() {
builder = builder.query(&query_pairs);
}
if let Some(val) = inputs.get("Notion_Version") {
builder = builder.header("Notion-Version", super::message_to_str(val));
}
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert(
"error".to_string(),
Message::Error(format!("GET /users failed: {}", e).into()),
);
}
}
Ok(output)
}
#[actor(
NotionReadBotUserActor,
inports::<100>(Notion_Version),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn notion_read_bot_user(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let endpoint = "/users/me".to_string();
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout_compat(Duration::from_secs(30))
.build()?;
let mut builder = client.get(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
if let Some(val) = inputs.get("Notion_Version") {
builder = builder.header("Notion-Version", super::message_to_str(val));
}
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert(
"error".to_string(),
Message::Error(format!("GET /users/me failed: {}", e).into()),
);
}
}
Ok(output)
}
#[actor(
NotionCreateCommentActor,
inports::<100>(parent, discussion_id, rich_text, Notion_Version),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn notion_create_comment(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let endpoint = "/comments".to_string();
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout_compat(Duration::from_secs(30))
.build()?;
let mut builder = client.post(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
if let Some(val) = inputs.get("Notion_Version") {
builder = builder.header("Notion-Version", super::message_to_str(val));
}
let mut body = serde_json::Map::new();
if let Some(val) = inputs.get("parent") {
body.insert("parent".to_string(), val.clone().into());
}
if let Some(val) = inputs.get("discussion_id") {
body.insert("discussion_id".to_string(), val.clone().into());
}
if let Some(val) = inputs.get("rich_text") {
body.insert("rich_text".to_string(), val.clone().into());
}
if !body.is_empty() {
builder = builder.json(&serde_json::Value::Object(body));
}
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert(
"error".to_string(),
Message::Error(format!("POST /comments failed: {}", e).into()),
);
}
}
Ok(output)
}
#[actor(
NotionListCommentsActor,
inports::<100>(block_id, start_cursor, page_size, Notion_Version),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn notion_list_comments(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let endpoint = "/comments".to_string();
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout_compat(Duration::from_secs(30))
.build()?;
let mut builder = client.get(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
let mut query_pairs: Vec<(&str, String)> = Vec::new();
if let Some(val) = inputs.get("block_id") {
query_pairs.push(("block_id", super::message_to_str(val)));
}
if let Some(val) = inputs.get("start_cursor") {
query_pairs.push(("start_cursor", super::message_to_str(val)));
}
if let Some(val) = inputs.get("page_size") {
query_pairs.push(("page_size", super::message_to_str(val)));
}
if !query_pairs.is_empty() {
builder = builder.query(&query_pairs);
}
if let Some(val) = inputs.get("Notion_Version") {
builder = builder.header("Notion-Version", super::message_to_str(val));
}
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert(
"error".to_string(),
Message::Error(format!("GET /comments failed: {}", e).into()),
);
}
}
Ok(output)
}